git stash blunder: git stash pop and ended up with merge conflicts
Solution 1
See man git merge (HOW TO RESOLVE CONFLICTS):
After seeing a conflict, you can do two things:
Decide not to merge. The only clean-ups you need are to reset the index file to the HEAD commit to reverse 2. and to clean up working tree changes made by 2. and 3.; git-reset --hard can be used for this.
Resolve the conflicts. Git will mark the conflicts in the working tree. Edit the files into shape and git add them to the index. Use git commit to seal the deal.
And under TRUE MERGE (to see what 2. and 3. refers to):
When it is not obvious how to reconcile the changes, the following happens:
The HEAD pointer stays the same.
The MERGE_HEAD ref is set to point to the other branch head.
Paths that merged cleanly are updated both in the index file and in your working tree.
...
So: use git reset --hard
if you want to remove the stash changes from your working tree, or git reset
if you want to just clean up the index and leave the conflicts in your working tree to merge by hand.
Under man git stash (OPTIONS, pop) you can read in addition:
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.
Solution 2
I had a similar thing happen to me. I didn't want to stage the files just yet so I added them with git add
and then just did git reset
. This basically just added and then unstaged my changes but cleared the unmerged paths.
Solution 3
If, like me, what you usually want is to overwrite the contents of the working directory with that of the stashed files, and you still get a conflict, then what you want is to resolve the conflict using git checkout --theirs -- .
from the root.
After that, you can git reset
to bring all the changes from the index to the working directory, since apparently in case of conflict the changes to non-conflicted files stay in the index.
You may also want to run git stash drop [<stash name>]
afterwards, to get rid of the stash, because git stash pop
doesn't delete it in case of conflicts.
Solution 4
Note that Git 2.5 (Q2 2015) a future Git might try to make that scenario impossible.
See commit ed178ef by Jeff King (peff
), 22 Apr 2015.
(Merged by Junio C Hamano -- gitster
-- in commit 05c3967, 19 May 2015)
Note: This has been reverted. See below.
stash
: require a clean index to apply/pop
Problem
If you have staged contents in your index and run "
stash apply/pop
", 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.
In other words:
"
git stash pop/apply
" forgot to make sure that not just the working tree is clean but also the index is clean.
The latter is important as a stash application can conflict and the index will be used for conflict resolution.
Solution
We can make this safer by refusing to apply when there are staged changes.
That means if there were merges before because of applying a stash on modified files (added but not committed), now they would not be any merges because the stash apply/pop would stop immediately with:
Cannot apply stash: Your index contains uncommitted changes.
Forcing you to commit the changes means that, in case of merges, you can easily restore the initial state( before
git stash apply/pop
) with agit reset --hard
.
See commit 1937610 (15 Jun 2015), and commit ed178ef (22 Apr 2015) by Jeff King (peff
).
(Merged by Junio C Hamano -- gitster
-- in commit bfb539b, 24 Jun 2015)
That commit was an attempt to improve the safety of applying a stash, because the application process may create conflicted index entries, after which it is hard to restore the original index state.
Unfortunately, this hurts some common workflows around "
git stash -k
", like:
git add -p ;# (1) stage set of proposed changes
git stash -k ;# (2) get rid of everything else
make test ;# (3) make sure proposal is reasonable
git stash apply ;# (4) restore original working tree
If you "git commit" between steps (3) and (4), then this just works. However, if these steps are part of a pre-commit hook, you don't have that opportunity (you have to restore the original state regardless of whether the tests passed or failed).
Solution 5
git restore --staged name-of-file-that-has--merge-conflict
Related videos on Youtube
Chirag Patel
I work on Rails, Javascript and lately PHP. Enjoy building stuff in general
Updated on September 11, 2021Comments
-
Chirag Patel over 2 years
I did a
git stash pop
and ended up with merge conflicts. I removed the files from the file system and did agit checkout
as shown below, but it thinks the files are still unmerged. I then tried replacing the files and doing agit checkout
again and same result. I event tried forcing it with-f
flag. Any help would be appreciated!chirag-patels-macbook-pro:haloror patelc75$ git status app/views/layouts/_choose_patient.html.erb: needs merge app/views/layouts/_links.html.erb: needs merge # On branch prod-temp # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: db/schema.rb # # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # unmerged: app/views/layouts/_choose_patient.html.erb # unmerged: app/views/layouts/_links.html.erb chirag-patels-macbook-pro:haloror patelc75$ git checkout app/views/layouts/_choose_patient.html.erb error: path 'app/views/layouts/_choose_patient.html.erb' is unmerged chirag-patels-macbook-pro:haloror patelc75$ git checkout -f app/views/layouts/_choose_patient.html.erb warning: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
-
VonC almost 9 yearsNote: restoring the state before the
git stash apply/pop
should be easier with Git 2.5 (Q2 2015), since the working tree now needs to be clean: see my answer below
-
-
phils over 12 yearsIn fact, even after you drop a stash, it's still possible (albeit more difficult) to retrieve it again, because the changeset still exists in the repository. stackoverflow.com/search?q=git+recover+dropped+stash
-
nalply over 12 yearsI didn't understand the answer but ended up doing exactly what is described here by finding it out by myself... :)
-
tanascius over 12 years@nalply: is that good or bad? You are welcome to improve my answer, where you didn't understand it in the first place ...
-
nalply over 12 yearsI think that source code revisioning is a complex problem domain. It is easy to get confused. I still think that your answer is good because it reconfirmed my approach.
-
sinelaw over 11 yearsThis seems to be better than using
reset --hard
because it doesn't overwrite your files (except the ones with merge problems). Thanks! -
Drew Noakes almost 11 yearsI didn't want to stage the files just yet so I added them -- doesn't
add
stage content from the working tree to the index? I don't think I understand why your answer works from the description. -
Aaron almost 11 years
git add
does stage them butgit reset
, which I do immediately after, unstages them. Essentially it clears the unmerged paths and returns me to my normal working tree by faking git out. -
bambams about 10 yearsYou don't need to
git add
if you're going togit reset
. Thegit reset
effectively "undoes" thegit add
.git reset
(--mixed
<- default) effectively does not touch the working directory so exactly what was in your working directory, merge conflicts and all, are left alone. The index (and technically the branch head) is reset though (without a ref they get reset back toHEAD
, which probably means no change for the branch head, and effectively undoes anygit add
done to the index, as well as clearing the unmerged paths state). -
artless noise about 10 yearsThe sequence, edit/resolve,
git reset
andgit stash drop
works well. It does whatgit stash pop
would have done with no conflicts. It does seem thegit add
is not needed; although it maybe useful it you have many files with conflicts. As each is resolved, they can be added andgit status
keeps track of them. -
Olga almost 10 yearsI was looking for something like git stash pop --continue after conflicts are merged. Last abstract helped me a lot =)
-
Thor84no almost 9 yearsNot only did it help me a lot to realise that the stash hasn't been removed as I assumed it had, but this explains why my stash kept growing even when I was certain I hadn't been forgetting to retrieve things from it.
-
Patrick M over 8 years"Applying the state can fail with conflicts; in this case, it is not removed from the stash list." This is the most important part of the post, in my opinion. Consider editing your answer to put it up front along with a the words DON'T PANIC in large, friendly letters. (+1 already though.) Thanks.
-
user3613932 about 4 yearsRan into the same issue. Simply call the git mergetool, and then do pop the stack once.
-
joanis over 2 yearsThis seems like a useful alternative solution, but can add an introduction explaining what effect this has exactly? There are several options one might want, and this one won't always be the right one.