我的合并脚本遇到了一个奇怪的问题 该脚本通常执行以下步骤:
- git 结帐 $source_branch
- git checkout -f $dest_branch
- git merge -Xtheirs --squash $source_branch -m "$commit_message">
- git commit -m $commit_message
- 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
、提交Q
和R
)与它们更改的内容(side
、提交A
、B
和C
)相结合的结果。 这与常规合并所做的组合相同。 但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(这并不聪明,一点也不聪明)任何合并冲突都可以通过盲目选择两种选择之一来解决。
我提到了上面的合并机制,并谈到了将"您的更改"(提交Q
和R
)与"它们的更改"(提交A
,B
和C
)相结合。 假设他们决定所有的水果都是橙子,因为回到承诺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
.