gitgit-stashgit-show

Git stash silently hides/deletes staged changes


Problem:

$ git status -s
MM myfile
$ git stash save
$ git show stash@{0}
# Only shows unstaged changes NOT staged changes

# To debug:
$ GIT_TRACE=2 git stash show
trace: exec: 'git-stash' 'show'
trace: run_command: 'git-stash' 'show'
trace: built-in: git 'rev-parse' '--git-dir'
trace: built-in: git 'rev-parse' '--show-toplevel'
trace: built-in: git 'config' '--get-colorbool' 'color.interactive'
trace: built-in: git 'config' '--get-color' 'color.interactive.help' 'red bold'
trace: built-in: git 'config' '--get-color' '' 'reset'
trace: built-in: git 'rev-parse' '--no-flags' '--symbolic' '--sq'
trace: built-in: git 'rev-parse' '--symbolic-full-name' 'refs/stash'
trace: built-in: git 'diff' '--stat' 'aaaa' 'bbbb'
trace: run_command: 'pager'
trace: exec: 'pager'
$ git diff --stat aaaa bbbb
# Shows both staged and unstaged changes
$ git stash apply --index
$ git status -s
MM myfile

Why doesn't git show stash@{0} not show the staged changes that were supposed to be part of the stash? It appears that git-stash is silently hiding the staged changes in a stash.


Solution

  • This is because git show stash@{0} is is the wrong command. You want git stash show stash@{0}.

    Unfortunately for stash usage, git show is a perfectly good command, and when you ask it to show a merge commit, it shows a combined diff. And, internally, stash commits have the form (but not the normal substance) of a merge commit, so that a combined diff is rarely any good at all—so git show is happy to show them, but shows them as empty.

    Since git stash show is really easy to typo/think-o as git show stash, you get very bad behavior. Just remember that when you see nothing, it may be a case of inverted word order.

    (It's also worth noting here that git stash show compares the stashed work-tree against the stash's parent. There is no git stash command to show the stashed index vs anything. To see the index vs the parent, use git diff stash@{number}^1 stash@{number}^2.)