902

I began making changes to my codebase, not realizing I was on an old topic branch. To transfer them, I wanted to stash them and then apply them to a new branch off of master. I used git stash pop to transfer work-in-progress changes to this new branch, forgetting that I hadn't pulled new changes into master before creating the new branch. This resulted in a bunch of merge conflicts and loss of a clean stash of my changes (since I used pop).

Once I recreate the new branch correctly, how I can I recover my stashed changes to apply them properly?

frederj
  • 1,483
  • 9
  • 20
acjay
  • 34,571
  • 6
  • 57
  • 100
  • 5
    Git is smart enough not to drop a stash if it doesn't apply cleanly – Snowmanzzz Mar 15 '22 at 08:18
  • 1
    ... and knowing that your stash is still on the `git stash list`, be free to use `git reset --hard`. i.e. when you stash-poped on the wrong branch and your conflict is obvious. – Sławomir Lenart Mar 07 '23 at 17:46

6 Answers6

1030

As it turns out, Git is smart enough not to drop a stash if it doesn't apply cleanly. I was able to get to the desired state with the following steps:

  1. To unstage the merge conflicts: git reset HEAD . (note the trailing dot)
  2. To save the conflicted merge (just in case): git stash
  3. To return to master: git checkout master
  4. To pull latest changes: git fetch upstream; git merge upstream/master
  5. To correct my new branch: git checkout new-branch; git rebase master
  6. To apply the correct stashed changes (now 2nd on the stack): git stash apply stash@{1}
Rakmo
  • 1,926
  • 3
  • 19
  • 37
acjay
  • 34,571
  • 6
  • 57
  • 100
  • 17
    Excellent thanks! #6 is really the answer I was looking for. Could add a `git stash drop` as the last step to get rid of the unwanted stash from #2. – austinmarton Oct 17 '14 at 00:39
  • 3
    #2 will not work if there are unmerged paths, it will instead output the error described here: http://stackoverflow.com/questions/5483213/fatal-git-write-tree-error-building-trees – Étienne Apr 30 '15 at 14:25
  • 7
    Not totally true--Git will keep the stash in the stash list if it failed to apply cleanly. See these docs about `git stash pop`: "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." (https://git-scm.com/docs/git-stash) – Carolyn Conway Sep 13 '16 at 19:46
  • 2
    This doesn't work properly. :-( It undid the changes but it left a bunch of noise in my files like: `<<<<<<< Updated upstream` `>>>>>>> Stashed changes` – Jez Nov 13 '17 at 00:13
  • @Jez You might try `git checkout -- .` to get back to a clean state. Or `git stash`, if you're worried you might possibly lose something important. – acjay Nov 13 '17 at 14:50
  • 33
    @call-me This is something I think people should actually do more often! Notice how the "Ask a question" form has a checkbox that let's you answer your own question in the same form :). This happens to me sometimes when I'm in the process of authoring a question that is stumping me, but in trying to tune the question to be good for StackOverflow, I end up figuring out the solution. This was a while ago, so I don't remember if that was the case here, but I'm guessing that's what happened. – acjay May 18 '18 at 14:35
  • 1
    @acjay Exactly! Sometimes I come to Stackoverflow to write a question when I'm stuck because the process of making sure I write a good question often helps me answer it myself (or even just find the correct question) :) – LeonardChallis Apr 26 '19 at 12:25
  • Some shells need additional quotes for #6: git stash apply 'stash@{1}', otherwise you get the error: unknown option: -encodedCommand – Stefanos Kargas Nov 07 '19 at 09:14
  • this answer is unnecessarily complex because it's involving branches, and they were not mentioned in the question – knocte Apr 22 '20 at 10:07
  • Step 1.5) `git add --all` – None Jun 11 '20 at 22:44
  • Step 4 could also be `git pull origin master`. Does the same, but is a bit more concise – user2428118 Jul 27 '20 at 20:07
505

Luckily git stash pop does not change the stash in the case of a conflict!

So nothing, to worry about, just clean up your code and try it again.

Say your codebase was clean before, you could go back to that state with: git checkout -f
Then do the stuff you forgot, e.g. git merge missing-branch
After that just fire git stash pop again and you get the same stash, that conflicted before.

Keep in mind: The stash is safe, however, uncommitted changes in the working directory are of course not. They can get messed up.

flori
  • 14,339
  • 4
  • 56
  • 63
  • 33
    What I understand is that you can simply cleanup and pop again, but you can't *undo* it. If the pop gets mixed with other uncommitted changes, then you have to clean up manually. – haridsv Mar 24 '17 at 06:22
  • This is a very simple solution and worked great for me. It assumes that you can revert everything that has changed locally (there were no changes before/after the stash was popped) which I think works for most situations. If you needed to save some additional changes that happened before realizing that this was a problem, you should be able to commit those files before forcing a checkout in most cases. – Project707 Jul 21 '17 at 22:39
  • This was not the case for me. I called `git stash pop` it attempted to auto-merge, conflicted, and kept it. – Trevor Hickey Aug 13 '18 at 21:49
  • 1
    @TrevorHickey The point of this answer was that the stash stays as it is in case of a conflict, that you can call `git stash pop` as often you need until it ends without a conflict. So after your conflict, yes, the working directory is in mess, however, you can clean it up and call `git stash pop` again. – flori Aug 14 '18 at 07:35
  • 16
    this command to undo last stash apply is very useful: `git checkout -f` ! – Lafi Feb 19 '19 at 15:41
  • 3
    what does git checkout -f mean? – Aparna Jun 11 '19 at 08:52
  • I was partially wrong. The stash that had some of my work was @1, not pop (not sure why exactly). However, the new files weren't included in that stash. I'm sure I did something more convoluted that messed this up. – Wylliam Judd Aug 31 '20 at 22:51
  • 1
    `git checkout -f branchname` means "checkout branchname, and f = force, meaning I know there are uncommitted changes where I am right now, I don't care just dump everything. Since `git stash pop` doesn't actually "pop" if there are conflicts, I was able to do the force checkout and then `git stash pop` again on the correct branch. Easy peasy. – Mike K Jul 22 '21 at 22:09
113

The simplest command, it works everywhere including git stash pop, git merge etc.

But careful! You'll lose all changes on untracked files. Tracked files stays intact

git reset --merge
Eric Palakovich Carr
  • 22,701
  • 8
  • 49
  • 54
Gabriel Petersson
  • 8,434
  • 4
  • 32
  • 41
44

Instructions here are a little complicated so I'm going to offer something more straightforward:

  1. git reset HEAD --hard Abandon all changes to the current branch

  2. ... Perform intermediary work as necessary

  3. git stash pop Re-pop the stash again at a later date when you're ready

fIwJlxSzApHEZIl
  • 11,861
  • 6
  • 62
  • 71
34
git checkout -f

must work, if your previous state is clean.

CAUTION: Beware–you'll lose all untracked changes to your files.

Allahbakash.G
  • 1,805
  • 1
  • 15
  • 17
2

If you're like me and had unstaged changes that you want to preserve, you can avoid losing that work by checking out a known stable version of each individual file from the stash. Hopefully those files are different than the ones you were working on. Also, this is why we use small commits as we go, dumb dumb.

git checkout main -- <file_with_conflicts>
charltoons
  • 1,951
  • 2
  • 18
  • 24