How to resolve git stash conflict without commit?

GitGit Stash

Git Problem Overview


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.

Git Solutions


Solution 1 - Git

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!

Solution 2 - Git

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.

Solution 3 - Git

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.

Solution 4 - Git

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.

Solution 5 - Git

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

Solution 6 - Git

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...

Solution 7 - Git

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

Solution 8 - Git

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

Solution 9 - Git

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.

Solution 10 - Git

According to https://stackoverflow.com/questions/3945826/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.

Solution 11 - Git

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.

Solution 12 - Git

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSvenView Question on Stackoverflow
Solution 1 - GitDavid Ferenczy RogožanView Answer on Stackoverflow
Solution 2 - GitscyView Answer on Stackoverflow
Solution 3 - GitComputerDruidView Answer on Stackoverflow
Solution 4 - GitstevenspielView Answer on Stackoverflow
Solution 5 - GitAaron GoldmanView Answer on Stackoverflow
Solution 6 - GitjacmknoView Answer on Stackoverflow
Solution 7 - GitMarco PontiView Answer on Stackoverflow
Solution 8 - GitcherishView Answer on Stackoverflow
Solution 9 - GitJammerView Answer on Stackoverflow
Solution 10 - GitsamgriggView Answer on Stackoverflow
Solution 11 - GitErik ZivkovicView Answer on Stackoverflow
Solution 12 - GitBishwas MishraView Answer on Stackoverflow