查找错误 git 合并的归咎提交



我的合并脚本遇到了一个奇怪的问题 该脚本通常执行以下步骤:

  1. git 结帐 $source_branch
  2. git checkout -f $dest_branch
  3. git merge -Xtheirs --squash $source_branch -m "$commit_message">
  4. git commit -m $commit_message
  5. git 推送起源 --all

它做其他事情,比如在主服务器上标记并创建一个新版本等。

现在到谜语 我发现在开发到release_candidate之间的最后一次合并中,在随机位置插入了一大块代码并破坏了产品 我查看了开发中的所有提交,但找不到一个具有此更改的提交

那么有没有办法找到被指责的提交,即使我在合并过程中压扁了它们?

...那么有没有办法找到被指责的提交,即使我在合并过程中压扁了它们?

简短的回答是否定的,但可能有一种方法可以恢复。

什么是壁球合并和做什么

这是壁球"合并"的危险之一(它根本不合并:它使用合并机制,即"合并为动词",但它产生单个普通提交,这不是合并,即不是">合并作为名词")。 例如,假设您有这个开始:

...--o--Q--R   <-- main

A--B--C   <-- side

即,在侧分支side上有三个不在主分支main上的提交,然后运行命令:

git checkout main && git merge --squash side

你得到的是这个:

...--o--Q--R--S   <-- main

A--B--C   <-- side

其中S是保存执行合并的工作树结果的新提交。 这个工作树结果是将你更改的内容(main、提交QR)与它们更改的内容(side、提交ABC)相结合的结果。 这与常规合并所做的组合相同。 但S是普通提交,而不是合并提交。 新提交S不存储提交C的哈希 ID。 Git无法通过提交S找到提交C

如果您进行了"真正的"合并,S将具有第二个向后链接,因此它不仅指向提交R,还会指向提交C。 Git 将能够使用它来定位A-B-C链中的任何问题。 但是你告诉 Git:不,我不想要讨厌的旧 A-B-C,把它们扔掉,只保留 S。这并没有错:例如,它可以保持主分支整洁。 但它限制了你以后回过头来查看A-B-C的能力:这既是它的巨大优势,也是它的巨大劣势。 这就是壁球合并的全部内容。

查找带有git bisect的错误

现在,仅仅因为你在进行合并时扔掉了A-B-C,并不意味着你完全抛弃了A-B-C如果您仍然有指向提交C的名称side,则可以使用它来查找提交C。 这将允许您在A-B-C链上使用git bisect

但是,由于此链根本没有连接到主分支(没有从S返回到主分支的链接),因此您必须在原始链上运行平分操作,而不是在挤压的合并链上运行平分操作。 如果错误结果在提交B中,则必须在提交S后的提交中单独修复它,在main分支上(除非可以从main完全删除S,并且您选择这样做)。

如果你没有原始提交——即你已经删除了侧分支名称side——那么你只需要将提交S视为它本来的样子:一个变化很大的大提交。 找到其中的错误。

自动分辨率很危险

任何Git 合并都可能出错,但添加-X theirs(或-X ours,就此而言)尤其危险,因为它告诉 Git(这并不聪明,一点也不聪明)任何合并冲突都可以通过盲目选择两种选择之一来解决。

我提到了上面的合并机制,并谈到了将"您的更改"(提交QR)与"它们的更改"(提交ABC)相结合。 假设他们决定所有的水果都是橙子,因为回到承诺o唯一使用的水果是橙子:

We have some recipes for you.
-Fruits grow on fruit trees.
+Oranges grow on orange trees.
Blah blah ...

同时,您在提交Q中添加了一些关于将苹果变成苹果酱的说明:

We have some recipes for you.
Fruits grow on fruit trees.
+To turn apples into applesauce, see recipe 3.
Blah blah ...

在这里,它们的变化——将水果限制为橙子——与你的变化相冲突。 一个普通的合并会告诉你,它不确定在这里做什么——你跑git merge -X theirs,告诉 Git:"每当有问题时,扔掉我的零钱,只拿走他们的。 因此,您添加的对苹果酱的引用被简单地抛弃了。 这可能没问题,但可能不行。 Git 不知道,它只是按照你的指示。

任何合并都需要某种审查(例如测试),但是"闭上眼睛,选择一个,希望最好"的合并需要额外的审查。 无论您将合并为谓词结果作为合并作为名词提交,还是作为忘记合并工作树的两个源的普通提交提交,都是如此。 如果您确实保留了侧分支(无论是通过真正的合并,还是仅通过保留它),并且立即发布合并结果,那么您就有机会对合并结果进行一些良好的测试,或者至少进行仔细校对。

如果没有,你就为这个问题做好了准备。

您可以在提交消息中指定源提交哈希。然后你不必搜索它。

您也可以停止使用--squash.

最新更新