Git pull在主分支中撤销提交?

4
一位同事(我们称其为Aaron)被分配负责长期改造网站的一个部分。他创建了一个名为“aaron”的新Git分支,所有更改都在此分支上进行。在他工作时,我继续维护整个网站,并将我的更改提交到“master”。
最终,Aaron将他的分支合并到“master”。这不知何故导致了我在合并时间和创建“aaron”分支的时间之间提交到“master”的所有更改被还原。如果输入git show <合并提交的哈希值>,可以查看我在Aaron工作期间更改的每个文件的差异。这些差异显示了我所做的每一项更改的还原。它看起来就像是Aaron手动将分支中每个文件的内容复制到“master”中,并提交了更改(但实际上他没有这样做,我只是想说明一下日志显示的内容)。
根据Aaron的说法,他没有做任何奇怪的事情。他说他只运行了git pull origin/aaron。
是什么导致了这种情况?git pull origin aaron会否还原我对master的所有更改?
另外,有没有一种轻松的方法可以恢复我的更改到master而不还原他的所有工作?
编辑1:
在合并后被还原的文件之一是foo.txt。因此,我执行了以下操作:
git checkout aaron
git log foo.txt

日志未反映出在创建“aaron”分支后对“foo.txt”的任何更改。我本来期望在“aaron”分支的日志中看到我的某些更改被还原,但是没有。那么,这是证明Aaron所声称的不只是简单地拉取了一下吗?
编辑2:
我说他输入了“origin/aaron”,但实际上他输入了“origin aaron”。我已经进行了修改。
编辑3:
根据下面的建议,我选择通过重写历史来解决这个问题。我现在相信问题是由于错误的解决冲突尝试导致的。

如果您使用gitk查看日志,是否有任何文件在Aaron的合并提交中被列为已更改? - asm
是的,所有被还原的文件都列在了更改列表中。差异非常清晰:对于我在主分支上所做的每个更改,差异中都有一个部分将更改还原。(即,您可以看到单独的行被改回去了。) - rlkw1024
抱歉,我错过了你之前的陈述。 - asm
2个回答

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 -- .的操作。

谢谢!我刚刚根据你的建议编辑了我的问题。你有什么想法? - rlkw1024
@Jarrett:是的,我认为这意味着他做了更多的事情,而不仅仅是 git pull origin/aaron - Lily Ballard
看这个问题,它曾经相当于只是 git merge origin/aaron。我开始起草一个相关的问题,但仍然无法确定即使是过时的 origin/aaron 引用也会导致这种情况。 - cmbuckley
@cbuckley:哦,所以我猜 git pull origin/foo 以前等同于 git merge foo,现在被禁止了,因为那是无用和令人困惑的。好好知道。 - Lily Ballard
1
@KevinBallard 实际上应该是 git merge origin/foo,这可能与 foo 不同。事实上,如果其他人在 origin 上推送到 foo,而我在本地副本的 foo 上提交并且没有以任何方式获取,则 fooorigin/fooorigin 上的 foo 现在是 3 个不同的引用! - cmbuckley
显示剩余2条评论

2

鉴于您看到的合并提交中发生了所有更改,这被称为恶意合并。 man gitglossary 这样定义它:

       evil merge
       An evil merge is a merge that introduces changes that do not appear in any
       parent.

这个意思在这个答案中有解释。对您来说需要知道的重要事情是,Git本身不会自动执行这个操作。创建一个“恶意合并”需要以某种方式进行人工干预。

我通常看到它发生的地方是当有人合并代码时因为冲突而感到困惑。例如,可能导致此问题的一件事是,如果Aaron开始拉取请求,由于冲突感到不知所措,并决定通过将他的文件复制到现有文件上来解决冲突。当他在这样做后进行合并提交时,你就会看到这个结果。

至于如何解决,如果可以的话,我建议你按照Kevin Ballard的建议去做。将主分支用git -reset --hard命令重置到合并之前的状态,然后重新进行合并。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接