progit2 icon indicating copy to clipboard operation
progit2 copied to clipboard

Is "git stash save --keep-index" explained correctly in Chapter 7?

Open ghost opened this issue 8 years ago • 11 comments

"Creative Stashing" section reads:

"There are a few stash variants that may also be helpful. The first option that is quite popular is the --keep-index option to the stash save command. This tells Git to not stash anything that you’ve already staged with the git add command."

Uh, are you sure about that? My understanding (and a quick test) suggests that "--keep-index" simply means that what is staged in the index remains staged, but it is still added to the stash. Am I misreading something?

ghost avatar Sep 29 '17 10:09 ghost

While I'm here, another question about stashing. Is there a simple way to display just the portion of a stash that is staged, or just the portion that is unstaged? If I run either of:

$ git stash show
$ git stash show -p

I always see the entirety of the stash -- that is, the changes in the working directory, with no indication of what part of that might already be marked as having been staged.

Given the picture of the structure of a stash in the man page, what I've come up with is, first, how to see just the part that has been staged:

$ git show stash@{0}^2

and just the part that is unstaged:

$ git diff stash@{0}^2 stash@{0}

Am I making this too difficult?

rpjday avatar Sep 29 '17 10:09 rpjday

Can you confirm whether or not I'm right about my suspicions here? If I am, I can submit a patch for that.

P.S. After some testing, yes, it appears that I'm right. "--keep-index" has no effect on what gets captured in the stash, it simply leaves staged content in the index (and, of course, the working tree). I'll submit a patch for that. Similarly, when applying/popping, "--index" always restores the entire stash to the working tree, it simply also tries to stage what was staged before.

rpjday avatar Oct 04 '17 10:10 rpjday

"--keep-index" has no effect on what gets captured in the stash, it simply leaves staged content in the index (and, of course, the working tree). I'll submit a patch for that.

Yup, confirmed. Here's the line from the docs:

If the --keep-index option is used, all changes already added to the index are left intact.

I look forward to that PR!

As for git stash show, here's the manpage section:

Show the changes recorded in the stash entry as a diff between the stashed contents and the commit back when the stash entry was first created. When no is given, it shows the latest one. By default, the command shows the diffstat, but it will accept any format known to git diff (e.g., git stash show -p stash@{1} to view the second most recent entry in patch form). You can use stash.showStat and/or stash.showPatch config variables to change the default behavior.

So you might want to check your config for stash.showPatch, because without the -p I just get a diffstat. You're right about the picture, too: here's what tig tells me about my test repo:

2017-10-05 10:37 Ben Straub ●─╮ [refs/stash] WIP on master: e14874e some content
2017-10-05 10:37 Ben Straub │ ● index on master: e14874e some content
2017-10-05 10:31 Ben Straub ●─╯ [master] some content
2017-10-05 10:31 Ben Straub ◎ initial

So you're right about how to tease out the separate parts. In practice, that's not generally how people use stashes, though. Since they're easy to pull out and look at, most people I know that use them just do stash apply, and use the normal worktree tools to check out what happened.

ben avatar Oct 05 '17 17:10 ben

Oh, it gets worse (I'll still submit a PR but it will likely be involved). So, we know that, regardless of what option(s) you use with "git stash", what is stashed will always include what was staged. However, add to that the options "--include-untracked" and "--all", which (respectively) add to the stash untracked files not being ignored and untracked files even if they are ignored, which I think are important variations and should be mentioned, at least briefly.

I started that discussion on the Git mailing list, and it kind of just took off from there.

I will ponder more how to revise this.

P.S. I'm pretty sure that, regardless of how much you pack into a stash, it will always have two components -- what was in the index, and everything else.

rpjday avatar Oct 05 '17 18:10 rpjday

I can barely keep up ... just yesterday, Git ML had a posting on the deprecation of "git stash save" in favour of "git stash push". Le sigh ...

rpjday avatar Oct 06 '17 12:10 rpjday

And "git stash push" has the same behavior for "--keep-index".

tgmayfield avatar Mar 22 '18 16:03 tgmayfield

I understood the same, when I used --keep-index I expected that the staged files are not added to the stash but they are.

The documentation should be clarified in a way that the staged files will be kept in the staged area AND copied to the stash.

Also consider an option to ignore the staged files (keep them on the index ONLY) when stash push

"Creative Stashing" section reads:

"There are a few stash variants that may also be helpful. The first option that is quite popular is the --keep-index option to the stash save command. This tells Git to not stash anything that you’ve already staged with the git add command."

Uh, are you sure about that? My understanding (and a quick test) suggests that "--keep-index" simply means that what is staged in the index remains staged, but it is still added to the stash. Am I misreading something?

emiliogq avatar May 28 '20 09:05 emiliogq

I have hit this issue a few times. This documentation line is not clear enough:

If the --keep-index option is used, all changes already added to the index are left intact.

I also want a way to staged working files excluding those changes in the index. Is there a workaround?

rdiez avatar Jan 08 '21 07:01 rdiez

Just ran into the same issue. From a general git tutorial, I expected --keep-index would not add staged files.

Is there a way to stash working files but not staged files?

Zireael07 avatar Mar 12 '22 11:03 Zireael07

Is there a way to stash working files but not staged files?

I ended up writing a script for that purpose:

https://github.com/rdiez/Tools/blob/master/Git/git-stash-only-unstaged-changes.sh

rdiez avatar Mar 12 '22 15:03 rdiez

stumbling on this again in 2023. Pretty common to hit this in the rebase workflow.

farazshaikh avatar Jun 12 '23 05:06 farazshaikh