Does lazygit have features similar to IDEA changeList?
Topic
A clear and concise description of what you want to discuss
Your thoughts What you have to say about the topic I hope I can only commit all the files in the specified changeList when I commit it.
+1 on this feature!
Primarily, I use this feature in IntelliJ to separate things that I want to commit and things that I need to keep on local.
https://www.jetbrains.com/help/idea/managing-changelists.html
I'm open to other people's workflow as well if they solve this in some way with lazygit's current featureset. I tried to replicate this functionality with stashes (apply stash and apply reverse stash, details here), but it is not good ux.
@stefanhaller, any thoughts on this?
I'm open to contributing as well.
My feeling is that lazygit doesn't need this feature because it makes it so easy to amend commits. It seems to me that IntelliJ is adding a feature on top of git that allows you to group uncommitted changes into change sets; but really, that's what commits are for. Instead of doing the work of assigning your changes to changeLists, simply commit them (yes, even if unfinished), as multiple commits; treat those as your changeLists. Then, when you want to add more changes to one of your "changeLists", select the corresponding commit and hit shift-A.
What's missing?
@stefanhaller Let me explain my scenario, I have some local changes (personal configurations) that I don't want to commit directly to git, I create an IDEA changelist called ignore, IDEA includes a change list called Changes by default, so that I can commit all the changes in the change list in IDEA by default.
But with lazygit I can't do that, I need to manually Stage, and find out which files don't need to be committed, and then commit them together.
Can you explain more what those "personal configurations" are? It sounds to me that those shouldn't be under version control in the first place?
e.g.: bootstrap.yml register-enabled: false
I don't want to register it with the development environment for local debugging, so I'll add it manually.
I see. You might look into git update-index --skip-worktree for solving this, independent of whether your git client is lazygit or the command line or some other client.
See https://www.brandonpugh.com/til/git/skip-worktree-ignore-modified-files/ for a good summary.
In a non-IDEA environment, this is exactly the solution I use, but it requires manually typing commands, which is not as convenient as the shortcut commands integrated with lazygit, and manually viewing or managing which files need to be ignored locally is cumbersome.
I don't know what other people's usage scenarios are, for me it would be better with this feature, but I'm fine without it.
but it requires manually typing commands, which is not as convenient as the shortcut commands integrated with lazygit,
Have you tried using custom commands for that?
Sounds good , I can use a custom command in [2]Files to ignore specific files, but awkwardly I don't seem to have a place to use a custom command to un-ignore them
I don't seem to have a place to use a custom command to un-ignore them
This can help:
customCommands:
- key: i
context: files
description: "Ignore file from worktree"
prompts:
- type: 'confirm'
title: 'Confirmation'
body: 'Do you want to ignore {{ .SelectedFile.Name }} from worktree?'
command: git update-index --skip-worktree {{ .SelectedFile.Name }}
- key: I
context: files
description: "Reconsider file for worktree"
prompts:
- type: 'menuFromCommand'
title: 'Choose File to reconsider'
key: 'FileToReconsider'
command: bash -c "git ls-files -v | grep ^S"
filter: S (?P<fileToReconsider>.*)
valueFormat: '{{ .fileToReconsider }}'
command: 'git update-index --no-skip-worktree {{ .Form.FileToReconsider }}'
Will use it for sometime and see how it works out for me.
Thanks folks for suggesting git update-index --skip-worktree!
@njkevlani Thank you so much for sharing this configuration! It works perfectly for my workflow and solves exactly what I needed.
However, I noticed that the i key conflicts with lazygit's built-in keybinding in the Files view (used for "Ignore or exclude file" - adding to .gitignore). To avoid this conflict, I modified the keybindings to use t and T instead:
customCommands:
- key: t
context: files
description: "Skip worktree - untrack file temporarily"
prompts:
- type: 'confirm'
title: 'Confirmation'
body: 'Do you want to skip worktree (untrack) {{ .SelectedFile.Name }}?'
command: git update-index --skip-worktree {{ .SelectedFile.Name }}
- key: T
context: files
description: "No-skip worktree - restore file tracking"
prompts:
- type: 'menuFromCommand'
title: 'Choose File to restore tracking'
key: 'FileToReconsider'
command: bash -c "git ls-files -v | grep ^S"
filter: S (?P<fileToReconsider>.*)
valueFormat: '{{ .fileToReconsider }}'
command: 'git update-index --no-skip-worktree {{ .Form.FileToReconsider }}'
Using t/T (as in "track"/"untrack") feels intuitive and avoids any conflicts. I'll be using this setup for a while to see how it works in practice.
Hope this helps others who might face the same issue! Again, thanks for the excellent solution! 🙌
This is really nice, great work coming up with this!
Now that I see this working so well, I do wonder if it should be a builtin feature. 😄 This would allow us to handle some of the awkward edge cases a little better (e.g. the ugly error message that you get when invoking t with a directory selected, or the error you get when invoking T when no files are hidden).
I'd probably call it Hide/Unhide (with tooltips explaining what this means exactly), and use h/H as keybindings. I find "untrack" to be a bit misleading here.
@stefanhaller Thank you for the thoughtful feedback! I'm glad you found this useful.
You're absolutely right about the edge cases. I just tested both scenarios:
- Invoking
ton a directory does show an ugly error message - Invoking
Twhen no files are hidden also produces an error
These are indeed awkward, and having this as a built-in feature with proper error handling would be much better! 👍
Regarding the keybindings, I agree that Hide/Unhide is more intuitive than track/untrack. However, I noticed that h is already used as a global keybinding for "navigate panel" (moving focus left between panels). Perhaps H/Shift+H could work, or maybe a different key combination altogether?
What do you think would be a good alternative keybinding that doesn't conflict with existing ones?
However, I noticed that
his already used as a global keybinding for "navigate panel"
Ah, I missed that, never use it myself. And it doesn't show up in the keybindings menu, I wonder if that's intentional.
Perhaps
H/Shift+Hcould work,
Erm, H and Shift+H are the same. 😄
I don't know, maybe we go with t/T then after all. It wouldn't be the first time that the keybinding has nothing to do with the command name (like g for "reset").
Another option we could consider is to not waste two keybindings, but only one. We could have a "Hide/unhide" command, bound to shift-H, and it would show a menu with two entries, "Hide" and "Unhide". Maybe not the greatest UX, just a measure to not pollute the global command space with too many fine-grained commands.
Anyone got a better suggestion?
Will shift+h work as a keybinding? I think it has the same "issue" as shift+l, i.e. it's scrolling the current panel horizontally.
Oh right, I forgot about that, too. :-/
Another option we could consider is to not waste two keybindings, but only one. We could have a "Hide/unhide" command, bound to shift-H, and it would show a menu with two entries, "Hide" and "Unhide". Maybe not the greatest UX, just a measure to not pollute the global command space with too many fine-grained commands.
I think the single-key menu approach makes sense! Since this is a relatively low-frequency operation, the extra menu step is totally acceptable, especially considering the benefit of not cluttering the global command space.
This would allow us to handle some of the awkward edge cases a little better (e.g. the ugly error message that you get when invoking t with a directory selected, or the error you get when invoking T when no files are hidden).
There are a couple of UX ideas that I could think of.
Having these commands behind conditions
We can put these commands behind conditions and handle failure cases.
It will look something like this:
In this solution, I have put the prompt message and command behind condition based on SelectedFile's availability.
Con that I could think of: a bit hacky.
Baking this as a built in feature
As a operation in files area, a natural expectation for skipping files from worktree would be that all the file under current path should be skipped from worktree (same way in which space stages all the files under current path).
That solves the issue that we faced when skipping files.
Now coming to no-skipping/reconsidering (for lake of better words) files for worktree, I see a good option is to have another subarea in Files area (next to Worktree, Submodule, etc) named Skipped Files. That section can have the files which currently skipped from worktree.
Cherry on the cake can be - we can use the same key for performing both the actions for skipping and no-skipping depending on the section we are in (files or Skipped Files)
Con that I could think of: It will confuse users when they skip files by mistake.
I see a good option is to have another subarea in
Filesarea (next toWorktree,Submodule, etc) namedSkipped Files.
I'm reluctant to add this, since it would then take a pretty prominent place in the UI for something that (I would assume) only very few users need.
However, I could imagine an entry in the Filtering dialog (ctrl-b) for hidden files.
I would also really like this feature native in lazygit since I too often use the "ignore some changes to that otherwise tracked file" with IDEA. And not having a "clean" staging area where I can just stage all the changes with a single keypress but have to watch out to not commit those things gets annoying quick and increases the risk of accidentally committing something I did not want.
The t/T bindings from @njkevlani and @awaken233 (thanks you two!) do help with that (although I had do wrap the file name in the cmd with " otherwise it sometimes errors out), but a more robust solution would be welcome!
As was stated before this could hopefully lead to better error handling and maybe even support to ignore entire folders or even new (i.e. untracked by git) files like local scratch files without needing to extend the .gitignore with entries noone else cares about.
Just wanted to throw my hat in the ring as another user that likes this niche workflow :D