我们称之为亚伦的一位同事被指派翻新一个网站的一部分作为一个长期项目。他创建了一个名为aaron
的新Git分支。他所有的改变都是在这个分支上进行的。在他工作的同时,我继续维护整个网站,将我的更改提交给master
。
最终,Aaron将他的分支合并到master
。这在某种程度上还原了我在合并时和首次创建master
分支的时间之间对aaron
所做的所有提交。如果我输入git show <hash of merge commit>
,我可以看到当Aaron在他的分支上工作时我改变的每个文件的差异。这些差异显示了我所做的每一项改变的回归。如果Aaron手动将其分支上的每个文件的内容复制到master
并提交更改,它看起来就像是这样。 (他没有这样做。我只是想说明日志显示的内容。)
根据亚伦的说法,他没有做任何奇怪的事情。他说他刚刚跑了git pull origin/aaron
。
导致这种情况的原因是什么? git pull origin aaron
是否可以将我的所有更改还原为master
?
此外,是否有一种简单的方法可以将我的更改恢复为master而不会恢复他的所有工作?
编辑1:
master
中更改过的一个文件,然后在合并后还原为foo.txt
。所以我这样做了:
git checkout aaron
git log foo.txt
在创建foo.txt
分支之后,日志不反映aaron
的任何更改。我有点期望在aaron
分支的日志中看到我的更改的恢复,但我没有。那么,这是最后的证据吗?Aaron做了一些其他事情,而不是他声称做过的简单拉动?
编辑2:
我曾说他输入了origin/aaron
,但实际上他键入了origin aaron
。我已经改变了它。
编辑3
根据以下建议,我选择通过重写历史来解决这个问题。我此时确信问题是由于误导解决冲突的尝试造成的。
答案 0 :(得分:5)
git pull origin/aaron
执行此操作的唯一方法是,如果他首先从master
合并到aaron
,则会放弃master
上的所有更改(可能是使用git merge -s ours master
)。
去检查历史记录。以前是否有master
合并到aaron
?他们会丢弃master
的变化吗?如果没有,那么唯一的解释是他不运行git pull origin/aaron
。
至于恢复更改,您可以退出合并并自行重新创建。这将改变历史,但如果你对此感到满意,那么这是最简单的解决方案。如果你不那就好了,那就稍微复杂了。在这种情况下,您将需要创建一个临时分支,退出他的合并,并正确地重新合并。然后返回掌握并运行git read-tree tempbranch
。这将使用临时正确合并[1]的结果更新您的索引,然后您可以提交它。
[1]:请注意,这不会修改您的工作树,因此您需要使用git checkout -- .
之类的内容进行修改。
答案 1 :(得分:2)
鉴于所有更改都发生在合并提交中,您将看到所谓的邪恶合并。 man gitglossary
以这种方式定义:
evil merge
An evil merge is a merge that introduces changes that do not appear in any
parent.
对this answer中的含义进行了解释。要知道的重要一点是,这不是git本身会做的事情。创建邪恶的合并需要以某种方式进行人为干预。
我经常看到它发生的地方是某人合并并因冲突而感到困惑。例如,可能导致这种情况的一件事是,如果aaron开始他的拉动,被冲突所淹没,并决定通过在现有文件的顶部复制他的文件来解决冲突是安全的。当他在执行此操作后进行合并提交时,您将完全看到这一点。
就修复它而言,如果可以的话,我会做Kevin Ballard建议的。 git -reset --hard
主分支回到合并之前的状态,然后重做合并。