[git] Aborting a stash pop in Git

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 keep. I don't just want to make the merge conflict disappear, but also to get my directory back to the state it was before the pop.

I tried git merge --abort, but git claimed no merge was in progress. Is there an easy way to abort a pop without destroying the changes I originally had in the directory?

This question is related to git git-stash

The answer is


Simple one-liner

I have always used

git reset --merge

I can't remember it ever failing.


Try using if tracked file.

git rm <path to file>
git reset  <path to file>
git checkout <path to file>

Some ideas:

  • Use git mergetool to split the merge files into original and new parts. Hopefully one of those is the file with your non-stash changes in it.

  • Apply the diff of the stash in reverse, to undo just those changes. You'll probably have to manually split out the files with the merge conflicts (which hopefully the above trick will work for).

I didn't test either of these, so I don't know for sure of they will work.


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.


Use git reflog to list all changes made in your git history. Copy an action id and type git reset ACTION_ID


If DavidG is correct that it didn't pop the stash because of the merge conflict, then you merely need to clean up your working directory. Quickly git commit everything you care about. (You can reset or squash the commit later if you're not done.) Then with everything you care about safe, git reset everything else that git stash pop dumped into your working directory.


If there were no staged changes before the git stash pop, as in the question, then the following two commands should work.

git diff --name-only --cached | xargs git checkout --ours HEAD
git ls-tree stash@{0}^3 --name-only | xargs rm

The first reverses any merges from the stash, successful or not. The second deletes any untracked files introduced by the stash.

From man git stash : The working directory must match the index. Which @DavidG points out, the stash pop will fail if any currently unstaged modified files conflict. As such, we shouldn't need to worry about unwinding merge conflicts beyond getting back to HEAD. Any remaining modified files are then unrelated to the stash, and were modified before the stash pop

If there were staged changes, I'm unclear on whether we can rely on the same commands and you may want to try @Ben Jackson's technique. Suggestions appreciated..

Here is a testing setup for all of the various cases https://gist.github.com/here/4f3af6dafdb4ca15e804

# Result:
# Merge succeeded in m (theirs)
# Conflict in b
# Unstaged in a
# Untracked in c and d

# Goal:
# Reverse changes to successful merge m
# Keep our version in merge conflict b
# Keep our unstaged a
# Keep our untracked d
# Delete stashed untracked c

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

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.


I solved this in a somewhat different way. Here's what happened.

First, I popped on the wrong branch and got conflicts. The stash remained intact but the index was in conflict resolution, blocking many commands.

A simple git reset HEAD aborted the conflict resolution and left the uncommitted (and UNWANTED) changes.

Several git co <filename> reverted the index to the initial state. Finally, I switched branch with git co <branch-name> and run a new git stash pop, which resolved without conflicts.


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.


Edit: From the git help stash documentation in the pop section:

Applying the state can fail with conflicts; in this case, it is not removed from the stash list. You need to resolve the conflicts by hand and call git stash drop manually afterwards.

If the --index option is used, then tries to reinstate not only the working tree's changes, but also the index's ones. However, this can fail, when you have conflicts (which are stored in the index, where you therefore can no longer apply the changes as they were originally).

Try hardcopying all your repo into a new dir (so you have a copy of it) and run:

git stash show and save that output somewhere if you care about it.

then: git stash drop to drop the conflicting stash then: git reset HEAD

That should leave your repo in the state it was before (hopefully, I still haven't been able to repro your problem)

===

I am trying to repro your problem but all I get when usin git stash pop is:

error: Your local changes to the following files would be overwritten by merge:
...
Please, commit your changes or stash them before you can merge.
Aborting

In a clean dir:

git init
echo hello world > a
git add a & git commit -m "a"
echo hallo welt >> a
echo hello world > b
git add b & git commit -m "b"
echo hallo welt >> b
git stash
echo hola mundo >> a
git stash pop

I don't see git trying to merge my changes, it just fails. Do you have any repro steps we can follow to help you out?


My use case: just tried popping onto the wrong branch and got conflicts. All I need is to undo the pop but keep it in the stash list so I can pop it out on the correct branch. I did this:

git reset HEAD --hard
git checkout my_correct_branch
git stash pop

Easy.