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

Mac*_*Mac 8 git

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

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

在此输入图像描述

编辑1:我不认为这是Undo一个尚未推送的Git合并的副本,因为提交被推送到原点以及我有其他提交错误后我想保留历史记录.

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

在此输入图像描述

编辑3:

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

me_*_*and 5

我可以看到三个选项:恢复合并、变基或过滤。

还原

正如其他人所提倡的,“正确”的解决方案是恢复合并——这意味着你不是“重写历史”,这通常被认为是一件好事,尤其是因为这意味着其他人都在处理这个代码不需要处理历史变化。

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

git revert -m 2 <sha-of-B>
Run Code Online (Sandbox Code Playgroud)

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

一个警告:如果你想将另一个分支合并到你的主分支中,你会因为 Git 认为该分支已经在主分支中而遇到麻烦。有几种解决方案,但最简单的 (IMO) 是将还原放在 master 的分支上,并将其合并到 master 中,并将其合并到另一个分支中。该分支可能看起来像它被分叉的任何版本的 master,此时您可以恢复恢复,并且当您将来合并时一切都会好起来的。

变基

变基可能是最简单的选择:git rebase <sha-of-B> master --onto <sha-of-C>.

这会将所有提交从 B 移动master到 C。问题在于它将“线性化”合并历史。图像中的合并历史非常简单,但如果您想保留历史或在更复杂的存储库上执行此操作,则可能会出现问题。

这也有一个问题,它是“重写历史”,使用此存储库的其他所有人都会发现他们正在处理与已恢复的代码分支完全不同的代码分支,因为从 C 开始的每次更改都将具有不同的 sha1 哈希.

过滤

使用git filter-branch将允许您准确地获得您在图像中寻找的内容,即保留合并历史记录,但它是最复杂的选项,并且仍然涉及重写历史记录。

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

过滤还原

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

进一步阅读