airblade / vim-gitgutter

A Vim plugin which shows git diff markers in the sign column and stages/previews/undoes hunks and partial hunks.
MIT License
8.35k stars 296 forks source link

Feature request: multiple staging areas #721

Closed jenstroeger closed 4 years ago

jenstroeger commented 4 years ago

What is the latest commit SHA in your installed vim-gitgutter?

da2c785221810b3d57479bb4b3678aabf32f3b88

What vim/nvim version are you on?

vim 8.1.2234


I keep running into a personal workflow issue where I have staged changes, and then other changes could/should commit independently of the already staged ones. Unfortunately, git has no easy support for multiple staging areas, but there’s some support using the GIT_INDEX_FILE variable. For more details see this SO thread or https://github.com/magit/magit/issues/2760.

Would it be useful/possible to add support for that variable to gitgutter? Even a fixed set of stages would help a lot, where I could stage hunks etc to a selected stage, e.g. <leader>hs2 (use stage 2) with <leader>hs defaulting to main index…

Thanks!

airblade commented 4 years ago

I sometimes run into this myself. I usually end up making a number of small, temporary commits as I notice different things, and then afterwards combine the ones that belong together with git-rebase.

So I see what you're getting at. But I think this would add complexity which I don't want to support. Sorry!

jenstroeger commented 4 years ago

Even if you’d hardwire four stages only, for example? Can I bribe you with a cuppa camomile tea? 😉

Too bad… (Want me to close the issue?)

airblade commented 4 years ago

I don't think the exact number of extra staging areas makes a difference.

Staging a hunk into a specific staging area probably isn't too hard. But it's not clear to me which staging area to diff against when generating the signs.

For example, let's say you have two staging areas, A and B, both empty, and a file with two separate changes, P and Q. And let's say the plugin is diffing against A. Signs are shown for both changes. Then you stage P into B. The signs don't change because as far as A is concerned, P is still unstaged. That seems quite confusing. You could add a command to switch the "reference" staging area to B, so P's signs disappear. But then you need to keep track of which is the reference staging area at any one time.

If you have several logically distinct changes happening at the same time, they have to be separated out somewhere. I prefer doing it after committing (with git-rebase); you prefer to do it before committing (with multiple staging areas). Since only one staging area can be diffed against at a time, I feel the multiple staging area approach doesn't fit vim-gitgutter as well.

airblade commented 4 years ago

You could try it out by setting 'g:gitgutter_git_executable to something like "GIT_INDEX_FILE=/path/to/index1 git" and then setting up a few maps to change the value to point to the different staging areas.

jenstroeger commented 4 years ago

But it's not clear to me which staging area to diff against when generating the signs.

That’s part of the referenced conversations. Personally, I’d be happy to select a staging area like I select a branch and then work from there. But that’s probably outside of the scope of this vim plugin.

airblade commented 4 years ago

I think the plugin can already support your workflow if you set up a few maps (untested):

" To switch the 'active' staging area, i.e. what we diff against for the signs
map <leader>i1 let g:gitgutter_git_executable="GIT_INDEX_FILE=/path/to/index1 git"
map <leader>i2 let g:gitgutter_git_executable="GIT_INDEX_FILE=/path/to/index2 git"
...

" To stage to a specific staging area
map <leader>hs1 let g:gitgutter_git_executable="GIT_INDEX_FILE=/path/to/index1 git" | <Plug>(GitGutterStageHunk)
map <leader>hs2 let g:gitgutter_git_executable="GIT_INDEX_FILE=/path/to/index2 git" | <Plug>(GitGutterStageHunk)
...