How to resolve git stash conflict without commit?

一个人想着一个人 提交于 2019-11-28 14:54:49

Don't follow other answers

Well, you can follow them :). But I don't think that doing a commit and then resetting the branch to remove that commit and similar workarounds suggested in other answers are 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 reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

So let's do what Git suggests (without doing any useless commits):

  1. Manually (or using some merge tool, see below) resolve the conflict(s).
  2. Use git reset to mark conflict(s) as resolved and unstage the changes. You can execute it without any parameters and Git will remove everything from the index. You don't have to execute git add before.
  3. Finally, remove the stash with git stash drop, because Git doesn't do that on conflict.

Translated to the command-line:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

Explanation of the default behavior

There are two ways of marking conflicts as resolved: git add and git reset. While git reset 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 reset 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 majority of conflicts automatically itself. It's huge time-saver!

scy

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.

ComputerDruid

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.

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

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

Marco Ponti

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

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

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.

samgrigg

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.

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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!