git bisect 如何选择一个没有第一个好的提交作为祖先的提交? (使用 --first-parent)

How can git bisect pick a commit that doesn't have the first good commit as an ancestor? (using --first-parent)

我有一个存储库,它使用“主干”流程,功能分支合并并创建合并提交,并且我正在使用 bisect 尝试查找引入问题的时间。问题识别过程涉及与已知良好提交结果的比较,因此我使用 git bisect --first-parent(2.29 中的新功能)跳过不在“主干”分支中的提交(识别导致问题的合并提交是对我来说足够了)。

但是,git bisect --first-parent 正在选择没有我作为祖先的第一个良好提交的提交,我不确定这怎么可能。

在下面的示例中,提交 2 是好的,而 4 是错误的。

  a 
 / \
1-2-3-4

如果没有 --first-parent,我希望功能分支提交 a 包含在二分中,但是如果有 --first-parent,我希望它跳过那个提交,只测试合并提交,3.

我已经在一个小型存储库上测试了它,它的行为符合我的预期,但是我更大、更复杂的存储库不会跳过没有 first-good 作为祖先,我正在努力理解为什么。

我的命令是

# both "first-good" and "first-bad" are tags on the "trunk" branch
git bisect start --first-parent
git merge-base --is-ancestor first-good first-bad  # returns TRUE
git merge-base first-good first-bad                # returns first-good
git checkout first-bad 
git bisect bad
git checkout first-good
git bisect good 
git merge-base --is-ancestor first-good HEAD       # returns FALSE - why/how?
git merge-base first-good HEAD                     # returns some other commit - why/how?

在git@47f0f94bc7 中,如果 first-good 提交仅作为合并提交的第二个父级存在于主线中,则会观察到问题中描述的行为。考虑到标志的名称,我想这在某种程度上是意料之中的,但是如果您依赖 first-good 提交进行工作构建,这确实会导致混淆行为,因为并非所有的二等分都包含该提交。

例如:

  a - b - c   # "trunk2"
 /   /  
1 - 2         # "trunk1"

# 2 is the `first-good` commit
# c is the `first-bad` commit

git bisect --first-parent 将选择 a 作为测试提交,即使它不是第一个已知良好提交 2 的祖先。在这种情况下,它似乎 back-track 到 a,这是 不是 first-good 的祖先的第一个提交。它不测试 1,因为它是 first-good 的祖先,因此可以假定它也很好。

在此示例中,带或不带 --first-parents 标志的行为是相同的。从 trunk2 开始并合并回 trunk2 的其他分支将继续被跳过。

虽然我相当确定这是“正确的”行为,并且对于大多数用例,用户不会注意到差异,但手册页可以使用此行为的一些详细信息 and/or 警告当 first-good 提交仅作为第二个父级存在时给出。

这发生在我的例子中,因为我们在某个时候“re-trunked”,提交同时进入两个分支。