I popped a stash and there was a merge conflict. Unlike the question that is listed as a duplicate, I already had some uncommitted changes in the directory which I wanted to
I could reproduce clean git stash pop
on "dirty" directory, with uncommitted changes, but not yet pop that generates a merge conflict.
If on merge conflict the stash you tried to apply didn't disappear, you can try to examine git show stash@{0}
(optionally with --ours
or --theirs
) and compare with git statis
and git diff HEAD
. You should be able to see which changes came from applying a stash.
If you don't have to worry about any other changes you made and you just want to go back to the last commit, then you can do:
git reset .
git checkout .
git clean -f
OK, I think I have managed to find a work-flow that will get you back to where you need to be (as if you had not done the pop).
TAKE A BACKUP BEFOREHAND!! I don't know whether this will work for you, so copy your whole repo just in case it doesn't work.
1) Fix the merge problems and fix all the conflict by selecting all the changes that come from the patch (in tortoisemerge, this shows up as one.REMOETE (theirs)).
git mergetool
2) Commit these changes (they will already be added via the mergetool command). Give it a commit message of "merge" or something you remember.
git commit -m "merge"
3) Now you will still have your local unstaged changes that you started originally, with a new commit from the patch (we can get rid of this later). Now commit your unstaged changes
git add .
git add -u .
git commit -m "local changes"
4) Reverse the patch. This can be done with the following command:
git stash show -p | git apply -R
5) Commit these changes:
git commit -a -m "reversed patch"
6) Get rid of the patch/unpatch commits
git rebase -i HEAD^^^
from this, remove the two lines with 'merge' and 'reversed patch' in it.
7) Get your unstanged changes back and undo the 'local changes' commit
git reset HEAD^
I've run through it with a simple example and it gets you back to where you want to be - directly before the stash was popped, with your local changes and with the stash still being available to pop.
Ok, I think I have worked out "git stash unapply". It's more complex than git apply --reverse
because you need reverse merging action in case there was any merging done by the git stash apply
.
The reverse merge requires that all current changes be pushed into the index:
git add -u
Then invert the merge-recursive
that was done by git stash apply
:
git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
Now you will be left with just the non-stash changes. They will be in the index. You can use git reset
to unstage your changes if you like.
Given that your original git stash apply
failed I assume the reverse might also fail since some of the things it wants to undo did not get done.
Here's an example showing how the working copy (via git status
) ends up clean again:
$ git status
# On branch trunk
nothing to commit (working directory clean)
$ git stash apply
Auto-merging foo.c
# On branch trunk
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: foo.c
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git add -u
$ git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
Auto-merging foo.c
$ git status
# On branch trunk
nothing to commit (working directory clean)
I have always used
git reset --merge
I can't remember it ever failing.
I'm posting here hoping that others my find my answer helpful. I had a similar problem when I tried to do a stash pop on a different branch than the one I had stashed from. On my case I had no files that were uncommitted or in the index but still got into the merge conflicts case (same case as @pid). As others pointed out previously, the failed git stash pop did indeed retain my stash, then A quick git reset HEAD plus going back to my original branch and doing the stash from there did resolve my problem.