772

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,323
  • 8
  • 20
acjay
  • 31,546
  • 5
  • 54
  • 98

5 Answers5

896

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,588
  • 2
  • 17
  • 34
acjay
  • 31,546
  • 5
  • 54
  • 98
  • 15
    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
  • 1
    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
  • 7
    Strange how this answer and the question are posted on the **exact** same minute – call-me May 18 '18 at 07:40
  • 31
    @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
463

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
  • 12,120
  • 3
  • 49
  • 59
  • 30
    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
  • 13
    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
  • @WylliamJudd I feel sorry! Which part didn't work? What happened? – flori Aug 31 '20 at 20:56
  • 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
  • `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
53
git reset --merge

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

Careful! You'll lose all changes on untracked files.

Gabriel Petersson
  • 5,310
  • 2
  • 23
  • 26
41

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
  • 9,849
  • 6
  • 53
  • 64
34
git checkout -f

must work, if your previous state is clean.

Allahbakash.G
  • 1,681
  • 1
  • 14
  • 16