713

As asked in this question, I also want to know how to resolve a conflicting git stash pop without adding all modifications to a commit (just like "git stash pop" without a conflict does).

My current approach is very uncool because I do it this way:

git stash pop  # -> CONFLICT
git stash drop
# [resolve conflict]
# [add conflict files]
git reset HEAD # <all files that are in commit-mode>

How to reproduce:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27: Added a new file called 'third' to the example to show that workarounds like the solution from scy only work for empty HEADs but don't fix the initial problem that the HEAD doesn't have the same content like for a git stash pop without a conflict.

5
  • So you git add your resolved conflict files, effectively staging them in the index, and you'd want to not have them in our index?
    – Romain
    Commented Oct 14, 2011 at 8:55
  • Yes, thats right. I just want the behavior that git stash pop has when no conflict occurs (but with notification which files need to be merged).
    – Sven
    Commented Oct 14, 2011 at 10:22
  • 2
    Seems like the answer for this is here: stackoverflow.com/questions/3945826/git-stash-questions. In the chosen answer, on the 4th comment, Adam explains why git does this. Commented Feb 10, 2012 at 13:41
  • 3
    @Patrick Thank you for this information - so it seems there will be no solution available because its "by design"
    – Sven
    Commented Feb 24, 2012 at 7:19
  • The direct link to the comment @Patrick is referring to is stackoverflow.com/questions/3945826/…
    – Emeka Elo
    Commented Nov 14, 2022 at 12:32

13 Answers 13

864

Clean solution

The following solution seems to be much cleaner to me and it's also suggested by the Git itself — try to execute git status in the repository with a conflict:

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

Note: The restore command has been introduced in Git version 2.23.0. Older versions of Git suggested to use the command git reset HEAD <file>... instead of git restore --staged <file>.... You could also use git reset to unstage any and all files in the staging area (called the index). Restore command's equivalent is git restore --staged . (the dot is necessary and it specifies any file). Currently, any of those commands may be used and the outcome is the same. If you want to learn about the differences between those commands, check the documentation.

So let's do what Git suggests (without making and reverting any pointless commits):

  1. Manually (or ideally using some merge tool, see below) resolve the conflict(s).
  2. Use git restore --staged . to mark conflict(s) as resolved and unstage all files in the staging area. If you want to unstage only specific files, use the command git restore --staged <file> instead. You don't have to execute git add before.
  3. Finally, remove the stash with git stash drop, because Git doesn't do that automatically on conflict.

Translated to the command-line commands:

$ git stash pop

# ...resolve conflict(s)

$ git restore --staged .

$ git stash drop

Explanation of the default behavior

There are two ways of marking conflicts as resolved: git add and git restore --staged <file>.... While git restore --staged <file>... marks the conflicts as resolved and removes files from the index, git add also marks the conflicts as resolved, but keeps files in the index.

Adding files to the index after a conflict is resolved is on purpose. This way you can differentiate the changes from the previous stash and changes you made after the conflict was resolved. If you don't like it, you can always use git restore --staged . to remove everything from the index.

Merge tools

I highly recommend using any of 3-way merge tools for resolving conflicts, e.g. KDiff3, Meld, etc., instead of doing it manually. It usually solves all or the majority of conflicts automatically itself. It's huge time-saver!

17
  • 32
    @kamalpal it seems to be needed when git stash pop fails with conflicts. Commented Mar 1, 2016 at 20:53
  • 25
    @kamalpal yes, Git even notifies you that stash has not been dropped in a case of conflict. And the question was about such case, so you really need to execute git stash drop unless you want to keep that stash. Commented Mar 2, 2016 at 11:21
  • 1
    @DavidFerenczyRogožan Git did not notify me at all that it did not drop the stash entry. Version 2.17.1 here. Commented Apr 30, 2020 at 2:05
  • 1
    For a stash with changes to multiple files: git stash pop does apply the changes to the files that don't result in conflicts, so it's only the files where conflicts occur that you have to fix. Commented Sep 7, 2020 at 15:51
  • 2
    Current versions of git now output the suggestion git restore --staged rather than git reset, which this answer to another question says has the same effect.
    – M. Justin
    Commented Feb 19, 2021 at 18:57
308
+50

Suppose you have this scenario where you stash your changes in order to pull from origin. Possibly because your local changes are just debug: true in some settings file. Now you pull and someone has introduced a new setting there, creating a conflict.

git status says:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

Okay. I decided to go with what Git suggested: I resolved the conflict and committed:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

Now my working copy is in the state I want, but I have created a commit that I don't want to have. How do I get rid of that commit without modifying my working copy? Wait, there's a popular command for that!

git reset HEAD^

My working copy has not been changed, but the WIP commit is gone. That's exactly what I wanted! (Note that I'm not using --soft here, because if there are auto-merged files in your stash, they are auto-staged and thus you'd end up with these files being staged again after reset.)

But there's one more thing left: The man page for git stash pop reminds us that "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." So that's exactly what we do now:

git stash drop

And done.

6
  • 39
    There's just a lot of inherit ugliness in deliberately having to do commit reset HEAD^... for something that should only affect the working tree.
    – user1115652
    Commented May 4, 2014 at 14:57
  • 9
    Why not just resolve the conflicts and then git add <resolved conflict files> followed by git reset HEAD? Commented Oct 27, 2015 at 20:23
  • Thanks for the suggestion but this doesn't fix the initial problem that this isn't the same behavior like git stash pop without a conflict. Just add another file to HEAD before doing the conflicting git stash pop and than your git commit -a -m WIP would also add the new file to the commit. But without a conflict, just the new file would stay in HEAD but not the git stash pop files.
    – Sven
    Commented Jun 27, 2016 at 6:04
  • 7
    I don't think it's necessary to commit first then undo commit. Simply reset from Dawid Ferenczy answer will do the same
    – vladkras
    Commented Jul 19, 2016 at 5:40
  • 4
    For windows users, the ^ is used as a special line continuation and will leave you sitting at a More? prompt instead of execution the command. Instead use: git reset --soft HEAD~1. See how-do-i-delete-unpushed-git-commits?
    – mrfelis
    Commented Jul 7, 2017 at 12:55
94

Instead of adding the changes you make to resolve the conflict, you can use git reset HEAD file to resolve the conflict without staging your changes.

You may have to run this command twice, however. Once to mark the conflict as resolved and once to unstage the changes that were staged by the conflict resolution routine.

It is possible that there should be a reset mode that does both of these things simultaneously, although there is not one now.

4
  • 2
    The reset mode is the one I search for - other workarounds are like the one I described and not practical for more than 5 files.
    – Sven
    Commented Nov 1, 2011 at 7:38
  • 25
    And use "git stash drop" afterwards to finish the "git stash pop".
    – David Liu
    Commented Dec 24, 2013 at 17:34
  • 2
    Although the question does not ask for this explicitly, it might be useful to update the answer to include "git stash drop" as the stash is not dropped automatically in the case of a conflict. Commented May 8, 2015 at 13:36
  • git reset is enough. Once. After you resolved the conflict (changed the files).
    – x-yuri
    Commented Jun 23, 2022 at 14:03
48
git checkout stash -- .

worked for me.

Note: this can be dangerous since it doesn't try to merge the changes from the stash into your working copy, but overwrites it with the stashed files instead. So you can lose your uncommitted changes.

5
  • This helped when "git pull --autostash" introduces unwanted merge commits and git checkout stash -- . unconditionally overwrites conflicts from stash Commented Jul 13, 2018 at 0:29
  • This helped me get out of "git hell" where the same conflict kept coming up even after following the git suggestions. I would do git stash pop, resolve the conflict, git add/commit, and git stash pop would produce the same issue. After running the above, I was able to run git stash pop and it worked.
    – steveb
    Commented Dec 23, 2020 at 19:26
  • This helped me in a situation where Github Actions build replace Docker image tags in Kubernetes manifests and push them from dev to staging branch. Creating PR to merge modified staging branch to main branch caused conflicts and this answer saved my bacon real good.
    – dzhi
    Commented Feb 2, 2021 at 13:33
  • And then git stash drop it went without saying. Commented Aug 2, 2021 at 19:04
  • Tried everything else, only this worked. My case was more complex triggered in github actions workflow. Nice work! Commented Feb 24, 2022 at 0:17
37
git add .
git reset

git add . will stage ALL the files telling git that you have resolved the conflict

git reset will unstage ALL the staged files without creating a commit

2
  • This is actually not a bad answer, it's pretty much like git add -u then git reset
    – ebob
    Commented Jun 5, 2017 at 17:04
  • 1
    clean and to the point
    – bareMetal
    Commented Oct 29, 2021 at 3:19
11

No problem there. A simple git reset HEAD is what you're looking for because it leaves your files as modified just like a non-conflicting git stash pop.

The only problem is that your conflicting files will still have the conflict tags and git will no longer report them as conflicting with the "both_modified" flag which is useful.

To prevent this, just resolve the conflicts (edit and fix the conflicting files) before running git reset HEAD and you're good to go...

At the end of this process your stash will remain in the queue, so just do a git stash drop to clear it up.

This just happened to me and googled this question, so the solution has been tested.

I think that's as clean as it gets...

6

It seems that this may be the answer you're looking for, I haven't tried this personally yet, but it seems like it may do the trick. With this command GIT will try to apply the changes as they were before, without trying to add all of them for commit.

git stash apply --index

here is the full explanation:

http://git-scm.com/book/en/Git-Tools-Stashing

5
  • Thanks for this hint, but this won't help when I already did git stash pop - or is there a way to revert this and to do git stash apply --index when I found out that git stash pop will run into a conflict?
    – Sven
    Commented Mar 2, 2012 at 6:53
  • I've added an example on how to produce this - imagine you're editing more than 10 files, so you don't know which of them you modified outside the stash.
    – Sven
    Commented Mar 2, 2012 at 6:59
  • 3
    If you look at the bottom of this post HERE it says that if you run git stash pop and it ends up with conflicts, the stash does not get removed...so you can run git reset --hard to undo the pop and then try the solution I suggested. Commented Mar 2, 2012 at 14:57
  • Just tried this and it doesn't work after you have a file in conflict state. Even if you fix the conflict manually.
    – Sam3k
    Commented Jul 21, 2014 at 15:19
  • This may still cause merge conflicts if your working tree contains staged/unstaged changes and you git stash --keep-index && git stash pop --index. The solution to this corner case is something along the lines of git stash --keep-index; do-stuff; git stash && git stash pop stash@{1} --index && git stash pop --index
    – CervEd
    Commented May 18, 2022 at 10:34
4

The fastest way I have found is to resolve the conflict, then do git add -u, and then do git reset HEAD, that doesn't even involve a commit.

2

git stash branch will works, which creates a new branch for you, checks out the commit you were on when you stashed your work, reapplies your work there, and then drops the stash if it applies successfully. check this

2

Answer for people having trouble with git stash -u not applying cleanly

What if you have a stash created with git stash -u? Then most of the answers to this question are invalid! Because as soon as you follow the advice given in the highest ranked answer (this one: https://stackoverflow.com/a/27382210/816017) - i.e. using git stash drop (my advice: don't do it) your unstaged files are gone.

That was a long-winded introduction to say the following:

If you have troubles with a Merge conflict when doing git stash pop, and you have used git stash -u, then one way to get out of that situation is this:

  • git stash branch my-stash-branch
  • Do whatever you need to fix the diff.
    • Hard diffs: Manually copy the offending files to a non-git folder, and then do git restore myfile, then apply the changes manually
    • Easy diffs: If the conflict is just in some throwaway file like Cargo.lock or yarn.lock just git restore Cargo.lock.
  • Do git stash -u again
  • git checkout my-actual-branch
  • git stash pop which should apply cleanly now, otherwise rinse & repeat
  • Remove the my-stash-branch once you are confident your changes have been applied correctly.

In short: the answer claiming "Don't follow other answers..." in a large bold font, is not the answer for everybody! ESPECIALLY not if you used git stash -u. Your changes may be lost!

Footnotes:

  • Unstaged files that have been lost by git stash drop can probably be found if you dig through git fsck - they're not in the reflog if I am not mistaken.
2
  • 1
    SAVED MY DAY! My case was exactly gits stash -u thanks!
    – mmway
    Commented May 29, 2023 at 11:44
  • 1
    Great idea to have a stash branch -- had not thought of that before!
    – ginna
    Commented May 1 at 19:56
1

According to git stash questions, after fixing the conflict, git add <file> is the right course of action.

It was after reading this comment that I understood that the changes are automatically added to the index (by design). That's why git add <file> completes the conflict resolution process.

1

please make sure that if you are using source tree for git, they will say that commit your changes or conflicts. Please don't do that,

Instead of opening your terminal and type

git add .
git stash

this source tree is telling 'commit your changes because they don't know if this change is conflicted or not but they are trying to take a backup for safety.

This git stash command will delete your merged conflicts. Thank you.

-2

Its not the best way to do it but it works:

$ git stash apply
$ >> resolve your conflict <<
$ >> do what you want to do with your code <<
$ git checkout HEAD -- file/path/to/your/file
1
  • 2
    this answer seems plain wrong to me, as it would discard all the changes to file/path/to/your/file , which is not what the OP asked, AFAIU Commented Jun 1, 2019 at 14:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.