合并冲突期间的`git stash`

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9009354/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 06:23:33  来源:igfitidea点击:

`git stash` during a merge conflict

gitmergegit-mergegit-stashmerge-conflict-resolution

提问by steven_moy

We've done something bad.

我们做了坏事。

We ran git stash saveduring a merge conflict, and now we can't restore our work.

我们git stash save在合并冲突期间运行,现在我们无法恢复我们的工作。

Things we've tried:

我们尝试过的事情:

git pull -Xours origin master
git stash apply --index

And:

和:

 git pull origin master
 git stash save --keep-index "merge conflicts"
 git stash apply stash@{1}

Please help!

请帮忙!

回答by Evan Krall

The issue seems to be that git stashdoesn't save a reference to the branch you were trying to merge in. During a merge, this is stored in a ref named MERGE_HEAD.

问题似乎是git stash没有保存对您尝试合并的分支的引用。在合并期间,它存储在名为 的引用中MERGE_HEAD

To fix it and get back to your previous state, you need to find the revision (let's pretend it's d7a9884a380f81b2fbf002442ee9c9eaf34ff68d) you were trying to merge in, and set MERGE_HEAD to it after you apply the stash.

要修复它并恢复到以前的状态,您需要找到您尝试合并的修订版(假设它是 d7a9884a380f81b2fbf002442ee9c9eaf34ff68d),并在应用存储后将 MERGE_HEAD 设置为它。

Then you can apply the stash (with --index to re-stage everything that was staged before), and set your MERGE_HEAD:

然后您可以应用存储(使用 --index 重新上演之前上演的所有内容),并设置您的MERGE_HEAD

git stash apply --index
git update-ref MERGE_HEAD d7a9884a380f81b2fbf002442ee9c9eaf34ff68d

回答by mmindenhall

I did the same thing today, and took a different approach (after trial and error) to get back to the state just prior to stashing so I could continue resolving conflicts and complete the merge.

我今天做了同样的事情,并采取了不同的方法(经过反复试验)回到存储之前的状态,这样我就可以继续解决冲突并完成合并。

First, after unstashing the partial merge in the destination branch, I captured a list of the files with remaining conflicts (text file or editor tab). This is just the list of unstaged files after unstashing, as the files with conflicts already resolved would have been staged prior to stashing.

首先,在目标分支中取消部分合并后,我捕获了具有剩余冲突的文件列表(文本文件或编辑器选项卡)。这只是取消存储后未暂存文件的列表,因为冲突已解决的文件将在暂存之前暂存。

$ git status
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   myproject/src/main/java/com/acme/package3/Class3.java
#   modified:   myproject/src/main/java/com/acme/package3/Class4.java
#

Next, I created a patch and reset the branch back to the pre-merge state:

接下来,我创建了一个补丁并将分支重置回合并前的状态:

$ git diff HEAD > ~/merge-with-resolved-conflicts.patch
$ git reset --hard HEAD

Then I created a temporary branch (derived from the merge destination branch), and applied the patch:

然后我创建了一个临时分支(派生自合并目标分支),并应用了补丁:

$ git checkout -b my-temp-branch
$ git apply ~/merge-with-resolved-conflicts.patch
$ git commit -a -m "Merge with resolved conflicts"

So the HEAD of my-temp-branch now contains everything that was merged, including files with conflicts resolved, and files with remaining conflicts.

因此, my-temp-branch 的 HEAD 现在包含合并的所有内容,包括已解决冲突的文件和具有剩余冲突的文件。

Then I switched back to original branch, merged again, and looked at the git status

然后我切换回原来的分支,再次合并,查看git status

$ git checkout my-branch
$ git merge other-branch
$ git status

The status shows the full list of files with conflicts:

状态显示有冲突的文件的完整列表:

# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#
#   both modified:      myproject/src/main/java/com/acme/package1/Class1.java
#   both modified:      myproject/src/main/java/com/acme/package2/Class2.java
#   both modified:      myproject/src/main/java/com/acme/package3/Class3.java
#   both modified:      myproject/src/main/java/com/acme/package3/Class4.java
#

Now I needed to compare these two lists of files. Any files in the second list but not the first had already been resolved (in this example, Class1.java and Class2.java). So for each of those files, I pulled in the version with conflicts resolved from the temporary branch (like cherry-pick, but for individual files rather than an entire commit):

现在我需要比较这两个文件列表。第二个列表中但不是第一个列表中的任何文件都已被解析(在本例中为 Class1.java 和 Class2.java)。因此,对于这些文件中的每一个,我都从临时分支中提取了冲突解决的版本(例如cherry-pick,但对于单个文件而不是整个提交):

$ git checkout my-temp-branch myproject/src/main/java/com/acme/package1/Class1.java
$ git checkout my-temp-branch myproject/src/main/java/com/acme/package2/Class2.java

Having done this, I was back to the state before the stash, so I could resume resolving the remaining conflicts and commit the merge.

完成此操作后,我回到了 stash 之前的状态,因此我可以继续解决剩余的冲突并提交合并。

回答by mmathieum

My solution to get out of this (git stash pop during a merge conflict) was:

我摆脱这种情况的解决方案(合并冲突期间的 git stash pop)是:

  • create and checkout a new (local) branch mytemporarybranch

    git branch mytemporarybranch && git checkout mytemporarybranch

  • commit into this mytemporarybranch

    git commit -m "my messy merge and squash"

  • checkout myoriginalbranch

    git checkout myoriginalbranch

  • merge correctly (no squash pop/apply this time!)

  • squashmerge the mytemporarybranchonto the myoriginalbranch

    git merge --squash mytemporarybranch

  • 创建并签出一个新的(本地)分支mytemporarybranch

    git branch mytemporarybranch && git checkout mytemporarybranch

  • 提交到这个我的临时分支

    git commit -m "我凌乱的合并和压缩"

  • 结帐我的原始分支

    git checkout myoriginalbranch

  • 正确合并(这次没有壁球弹出/应用!)

  • 壁球mytemporarybranch合并到myoriginal分支上

    git merge --squash mytemporarybranch

回答by manojlds

When you are in a conflicted state ( index and working directory), you will not be able to do git stash- it will give an error sating unmerged entries.

当您处于冲突状态(索引和工作目录)时,您将无法执行此操作git stash- 它会在未合并的条目中出现错误。

Make sure that you have really done a stash. See output of git stautsand git stash show

确保你真的做了一个藏匿。查看git stauts和的输出git stash show

回答by LeGEC

Given your last comment : you can use

鉴于您的最后一条评论:您可以使用

git stash megre --no-commit <branch>

to put the index in a "merge" state without committing the changes

将索引置于“合并”状态而不提交更改

then modify it with what you want :

然后用你想要的东西修改它:

if you have already worked out your merge in the stash :

如果您已经在 stash 中完成了合并:

git reset #to remove the "conflicts" flags
git checkout <initial commit> -- ./ #to revert everything to the previous working state,
git stash apply   #apply your changes

and once everything is in the desired state, git commit

一旦一切都处于理想状态, git commit



About bukzor's comment : there is actually a big difference between git checkout <tree-ish>and git checkout <tree-ish> -- <files>.

关于bukzor的评论:git checkout <tree-ish>和之间实际上存在很大差异git checkout <tree-ish> -- <files>

From the referenceon git checkout:

参考git checkout

  • git checkout <branch>: This form switches branches by updating the index, working tree, and HEAD to reflect the specified branch or commit.

  • git checkout [-p|--patch] <tree-ish> -- <pathspec>: When <paths> or --patch are given, git checkout does not switch branches. It updates the named paths in the working tree from the index file or from a named <tree-ish> (most often a commit).

  • git checkout <branch>: 这种形式通过更新索引、工作树和 HEAD 来切换分支以反映指定的分支或提交。

  • git checkout [-p|--patch] <tree-ish> -- <pathspec>: 当给定 <paths> 或 --patch 时,git checkout 不会切换分支。它从索引文件或命名的 <tree-ish>(通常是提交)更新工作树中的命名路径。

git checkout <initial commit>would indeed discard the merge informations.

git checkout <initial commit>确实会丢弃合并信息。

git checkout <initial commit> -- ./(note the extra -- ./), on the other hand, will keep the merge information, and revert every tracked file to its state in <initial commit>.

git checkout <initial commit> -- ./(注意额外的-- ./),另一方面,将保留合并信息,并将每个跟踪的文件恢复到<initial commit>.