合并冲突期间的`git stash`

时间:2012-01-25 19:56:18

标签: git merge git-merge git-stash merge-conflict-resolution

我们做错了。

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

我们尝试过的事情:

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

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

请帮忙!

5 个答案:

答案 0 :(得分:24)

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

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

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

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

答案 1 :(得分:1)

我今天也做了同样的事情,采取了不同的方法(经过试验和错误),以便在收起之前回到状态,这样我就可以继续解决冲突并完成合并。

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

$ 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
#

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

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

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

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

因此,my-temp-branch的HEAD现在包含已合并的所有内容,包括已解决冲突的文件以及仍存在冲突的文件。

然后我切换回原始分支,再次合并,并查看git状态

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

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

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

现在我需要比较这两个文件列表。第二个列表中的任何文件都已解析(在此示例中为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

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

答案 2 :(得分:0)

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

确保你真的已经藏匿了。请参阅git stautsgit stash show

的输出

答案 3 :(得分:0)

鉴于您的上次评论:您可以使用

git stash megre --no-commit <branch>

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

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

如果您已经在存储中计算出合并:

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

一旦所有内容都处于所需状态,git commit


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

来自reference上的git checkout

  • git checkout <branch>:此表单通过更新索引,工作树和HEAD来切换分支,以反映指定的分支或提交。

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

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

另一方面,

git checkout <initial commit> -- ./(注意额外的-- ./)将保留合并信息,并将每个跟踪的文件恢复为<initial commit>中的状态。

答案 4 :(得分:0)

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

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

      

    git branch mytemporarybranch&amp;&amp; git checkout mytemporarybranch

  • 提交到 mytemporarybranch

      

    git commit -m“我凌乱的合并和壁球”

  • 结帐 myoriginalbranch

      

    git checkout myoriginalbranch

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

  • 壁球 mytemporarybranch 合并到 myoriginal 分支

      

    git merge --squash mytemporarybranch