如何撤消git合并,但保留历史记录

时间:2015-10-27 17:02:53

标签: git

我们的存储库有一个主分支,但似乎我们的一个同事有一个具有不同历史的主分支。昨天他把他的主人合并成了主人并推了推。所以今天我们中的一些人已经开始工作了。当我们意识到这个问题时,已经过了几个小时的工作......

所以我的问题是如何撤消他的合并,但仍然保持今天的代​​码更改?左侧是我们目前的状态,右侧是我正在拍摄的。我应该改变吗?或者有办法撤消合并?这里最好的方法是什么?

enter image description here

编辑1:我不认为这是Undo a Git merge that hasn't been pushed yet的副本,因为提交被推送到原点以及我有其他提交错误后我想保留历史记录。

编辑2:我试图改变,问题是这位新秀在过去的两周内融入了他的主分支......所以,即使我还原,我也没有摆脱他创造的新“时间轴”。 ..只要我摆脱他的时间表,我就没有问题重写历史...

enter image description here

编辑3:

最后,我最终找到了一个未受影响的存储库版本,并回复了事件发生后所做的修改......

2 个答案:

答案 0 :(得分:2)

我可以看到三个选项:恢复合并,重新定位或过滤。

还原

"正确"正如其他人所倡导的那样,解决方案是恢复合并 - 这意味着你不会重写历史记录"这通常被认为是一件好事,尤其是因为它意味着其他所有人都在努力代码不需要处理历史变化。

但是,您不能按原样使用git revert,因为它不知道要保留历史记录的哪个分支。解决方案只是为Git提供额外的信息:

git revert -m 2 <sha-of-B>

-m 2指定您要保留第二个父级,即包含提交C的父级;切换到-m 1替代。

一个警告:如果你想将其他分支合并到主分支中,那么由于Git认为分支已经在主分支中,你会遇到麻烦。有几个解决方案,但最简单的(IMO)是将revert放在master上的分支上,并将其合并到master中,将其合并到另一个分支中。该分支看起来可能看起来像是分离出的任何版本的master,此时你可以恢复恢复,并且在将来合并时一切都会好的。

衍合

重新定位可能是最简单的选择:git rebase <sha-of-B> master --onto <sha-of-C>

这将把所有提交从B移到master到C.这个问题是它会&#34;线性化&#34;合并历史。图像中的合并历史记录非常简单,但如果您想保留历史记录或者在更复杂的存储库中执行此操作,则可能会出现问题。

这也抓住了它重写历史记录&#34;并且使用此存储库的所有其他人都会发现他们正在处理完全不同的代码分支到已被还原的那个,因为从C开始的每个更改都会有不同的sha1哈希值。

过滤

使用git filter-branch可以让您准确了解自己在图片中寻找的内容,即保留合并历史记录,但这是最复杂的选项,并且仍然需要重写历史记录。

实际上,您希望使用git filter-branch过滤提交以保留除一个duff合并之外的所有内容。这样做非常复杂,我不会尝试写指令;您需要合并--commit-filter以删除有问题的合并,并--tree-filter来反转合并的更改。

过滤redux

好的,这是我为了完整性而包含的第四种方法。您可以只签出C,然后手动挑选并合并您想要在主分支中进行的每个更改。

进一步阅读

答案 1 :(得分:1)

我要做的是找一个revert,你只是在寻找你刚刚在那个合并提交中合并的delta的反转,然后提交它。

将恢复提交拉到C分支,然后在C分支上恢复该提交并提交。双重否定将取消,您将保存所有历史记录,当您再次合并时,您将获得您正在寻找的结果。

Git Extensions有一个恢复提交的功能,这使得这很容易。