I make a change and then I git stash
and then I git stash apply
My question is
why after I git stash apply
I think that something may be wrong in your configuration as while git stash
records the state of the index and the working tree before resetting to the latest commit, git stash apply
should only attempt to restore the state of the index if you use the --index
option.
One possible point of confusion is that if you have conflict (i.e. there are merge conflicts introduced because the stash is being applied to a different commit where the files affected by the stash have been changed since the commit at which the stash was made), then if you use mergetool
to resolve the conflicts, mergetool
will automatically stage changes to the files on a successful resolution.
As Greg Hewgill states a simple reset will unstage all staged changes.
git reset
Why does git stash apply stage my changes?
Anything that will affect your working tree (like a git checkout -- afile) will first affect your index.
the index is the middle-man for moving things from your work-tree to the object-store AND for moving things from the object-store to your work-tree.
The index is also used by git stash apply
for recording merge conflicts, as the index has stage-n entries. See git merge:
For conflicting paths, the index file records up to three versions:
- stage 1 stores the version from the common ancestor,
- stage 2 from HEAD, and
- stage 3 from MERGE_HEAD (you can inspect the stages with
git ls-files -u
).
In the history of the evolution of git stash --apply
, two interesting events are to be noted:
In April 2011 (Git 1.7.5.1, commit e0e2a9c), stash
dropped the dirty worktree check on apply.
Before we apply a stash, we make sure there are no changes in the worktree that are not in the index. This check dates back to the original
git-stash.sh
, and is presumably intended to prevent changes in the working tree from being accidentally lost during the merge.However, this check has two problems:
It is overly restrictive. If my stash changes only file "
foo
", but "bar
" is dirty in the working tree, it will prevent us from applying the stash.It is redundant. We don't touch the working tree at all until we actually call merge-recursive.
But it has its own (much more accurate) checks to avoid losing working tree data, and will abort the merge with a nicer message telling us which paths were problems.So we can simply drop the check entirely.
Using the index to manage the merge done by a git stash apply
lead to another bug, detected in April 2015, Git 2.4.2, commit ed178ef:
stash
: require a clean index to applyIf you have staged contents in your index and run "
stash apply
", we may hit a conflict and put new entries into the index.
Recovering to your original state is difficult at that point, because tools like "git reset --keep
" will blow away anything staged.
We can make this safer by refusing to apply when there are staged changes.
If you find that your changes are unexpectedly staged, do:
git reset HEAD
I usually only see this if there is a conflict when applying the stashed changes. You will want to check to see whether this is the case before doing the git reset
.
The git stash
command is the most appropriate command for your use case. I use it all the time for exactly this purpose.