693

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.

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
Sven
  • 7,335
  • 4
  • 15
  • 14
  • 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 Oct 14 '11 at 08: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 Oct 14 '11 at 10:22
  • 2
    Seems like the answer for this is here: http://stackoverflow.com/questions/3945826/git-stash-questions. In the chosen answer, on the 4th comment, Adam explains why git does this. – Patrick Feb 10 '12 at 13:41
  • 3
    @Patrick Thank you for this information - so it seems there will be no solution available because its "by design" – Sven Feb 24 '12 at 07:19
  • The direct link to the comment @Patrick is referring to is https://stackoverflow.com/questions/3945826/git-stash-questions#comment4246601_3945995 – BrunoElo Nov 14 '22 at 12:32

13 Answers13

830

Don't follow other answers...

Well, you can follow them, of course. But I don't think that doing a commit and then resetting the branch to remove the commit you just created and similar workarounds suggested in other answers is the clean way to solve this issue.

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!

David Ferenczy Rogožan
  • 23,966
  • 9
  • 79
  • 68
  • 32
    @kamalpal it seems to be needed when `git stash pop` fails with conflicts. – Emile Bergeron Mar 01 '16 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. – David Ferenczy Rogožan Mar 02 '16 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. – Robert Siemer Apr 30 '20 at 02:05
  • This is so much more clear than many blog posts I've read on this topic. – coder_tim Aug 21 '20 at 17:57
  • 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. – Andrew Richards Sep 07 '20 at 15:51
  • 1
    I had a merge conflict while applying a stash. I resolved the conflicts, added the files and committed them. But then nothing happened. Normally I would do something like `git rebase --continue` for git to continue the progess. But I tried your command `git stash drop` and I just dropped my stash without the changes applied. Thank you for helping me loosing all my changes. – winklerrr Jan 07 '21 at 11:26
  • After `git stash drop`, I need to execute `git checkout -- "conflicted_file"` to discard the `conflicted_file`. – dustin2022 Jan 11 '21 at 05:02
  • 2
    Current versions of git now output the suggestion `git restore --staged` rather than `git reset`, which [this answer](https://stackoverflow.com/a/58003889/1108305) to another question says has the same effect. – M. Justin Feb 19 '21 at 18:57
  • 1
    The clean solution worked for me and, after using it, it makes way more sense than all others that I tested. Thank you very much, and enjoy your upvote :-) – A. Ocannaille May 06 '21 at 12:23
  • @M.Justin Oh, thank you for mentioning it! I didn't even notice it yet. I have updated the answer so it reflects the current state. – David Ferenczy Rogožan Jul 03 '21 at 23:38
  • @xuanduc611 I'm afraid you're doing something wrong. If you execute `git checkout -- "conflicted_file"`, you'll overwrite the file with the changes you just unstashed and where you have solved the conflict with the version from the most recent commit. So you'll completely lose the changes from the stash (since you dropped it already) and it completely doesn't make sense to unstash the changes, solve the conflict, drop the stash and finally overwrite and lose everything you just did. – David Ferenczy Rogožan Jul 03 '21 at 23:40
  • 1
    @winklerrr You have been following another answer probably. Nowhere I suggest making a commit, actually the opposite. Also, `git rebase --continue` doesn't make sense at all – you cannot continue with rebasing you didn't start. Stash has nothing to do with the rebase. And before making any irreversible operations, you should always double-check you won't lose anything. But there are [ways to restore a dropped stash](https://stackoverflow.com/questions/32517870/how-to-undo-git-stash-clear). I'm really sorry you lost your work, but my answer has helped hundreds of devs, only you had an issue. – David Ferenczy Rogožan Jul 03 '21 at 23:55
  • The `.` refspec doesn't specify any file. It specifies the current directory. What you want is `:/`. i submitted an edit – CervEd Dec 14 '21 at 11:20
  • git: 'restore' is not a git command. See 'git --help'. – SimZhou Nov 16 '22 at 06:04
  • I get "error: path <...> is unmerged" many times when I attempt to do `git restore --staged .` – Lou Aug 04 '23 at 11:18
  • `git restore --staged ` made me lose my stashed changes. I want the file to contain the edits, but not be committed or staged. – Eric Hansen Aug 28 '23 at 18:22
308

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.

tshepang
  • 12,111
  • 21
  • 91
  • 136
scy
  • 7,132
  • 2
  • 27
  • 35
  • 37
    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. –  May 04 '14 at 14:57
  • 9
    Why not just resolve the conflicts and then `git add ` followed by `git reset HEAD`? – BoltzmannBrain Oct 27 '15 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 Jun 27 '16 at 06:04
  • 7
    I don't think it's necessary to commit first then undo commit. Simply reset from [Dawid Ferenczy answer](http://stackoverflow.com/a/27382210/1713660) will do the same – vladkras Jul 19 '16 at 05: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?](https://stackoverflow.com/questions/3197413/how-do-i-delete-unpushed-git-commits) – mrfelis Jul 07 '17 at 12:55
  • instead of doing `git commit -a` wouldn't you just do `git reset HEAD` and have everything cool? – pqnet Apr 04 '18 at 17:10
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.

k107
  • 15,882
  • 11
  • 61
  • 59
ComputerDruid
  • 16,897
  • 1
  • 19
  • 28
  • 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 Nov 01 '11 at 07:38
  • 25
    And use "git stash drop" afterwards to finish the "git stash pop". – David Liu Dec 24 '13 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. – Abhishek Pathak May 08 '15 at 13:36
  • `git reset` is enough. Once. After you resolved the conflict (changed the files). – x-yuri Jun 23 '22 at 14:03
46
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.

David Ferenczy Rogožan
  • 23,966
  • 9
  • 79
  • 68
stevenspiel
  • 5,775
  • 13
  • 60
  • 89
  • This helped when "git pull --autostash" introduces unwanted merge commits and git checkout stash -- . unconditionally overwrites conflicts from stash – Alec Istomin Jul 13 '18 at 00: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 Dec 23 '20 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 Feb 02 '21 at 13:33
  • And then `git stash drop` it went without saying. – Daniel C. Sobral Aug 02 '21 at 19:04
  • Tried everything else, only this worked. My case was more complex triggered in github actions workflow. Nice work! – clementiano Feb 24 '22 at 00:17
34
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

Aaron Goldman
  • 829
  • 9
  • 7
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...

jacmkno
  • 1,189
  • 11
  • 25
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

Burkart
  • 462
  • 4
  • 9
Marco Ponti
  • 2,469
  • 1
  • 13
  • 4
  • 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 Mar 02 '12 at 06: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 Mar 02 '12 at 06:59
  • 3
    If you look at the bottom of this post [HERE](http://stackoverflow.com/questions/2840816/git-stash-blunder-git-stash-pop-and-ended-up-with-merge-conflicts) 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. – Marco Ponti Mar 02 '12 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 Jul 21 '14 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 May 18 '22 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.

Jammer
  • 542
  • 1
  • 6
  • 14
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

cherish
  • 1,370
  • 1
  • 11
  • 16
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.

Community
  • 1
  • 1
samgrigg
  • 11
  • 2
1

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.
Erik Živković
  • 4,867
  • 2
  • 35
  • 53
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.

Suramack
  • 111
  • 1
  • 5
-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
Bishwas Mishra
  • 1,235
  • 1
  • 12
  • 25
  • 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 – oromoiluig Jun 01 '19 at 14:17