33

We've done something bad.

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

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!

4

5 回答 5

33

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

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

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

git stash apply --index
git update-ref MERGE_HEAD d7a9884a380f81b2fbf002442ee9c9eaf34ff68d
于 2012-09-20T20:21:58.250 回答
2

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

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

$ 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

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

于 2013-08-10T00:19:34.693 回答
0

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

git stash megre --no-commit <branch>

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

然后用你想要的修改它:

如果您已经在 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

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


关于bukzorgit checkout <tree-ish>的评论:和之间其实有很大的不同git checkout <tree-ish> -- <files>

参考git checkout

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

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

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

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

于 2012-09-21T13:24:39.640 回答
0

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

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

    git branch mytemporarybranch && git checkout mytemporarybranch

  • 提交到这个mytemporarybranch

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

  • 结帐我的原始分支

    git checkout myoriginalbranch

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

  • squashmytemporarybranch合并到myoriginal分支上

    git merge --squash mytemporarybranch

于 2013-11-20T20:50:52.850 回答
0

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

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

于 2012-01-26T01:44:28.707 回答