如何在仅限更改了特定文件的提交记录上运行git bisect?

17

我有一个很久以前引入的 bug,对它进行测试非常痛苦。然而,我强烈怀疑引入这个 bug 的变更发生在一个特定的源代码文件中。

我能否在修改了该文件的一小部分提交上运行 git bisect?

3个回答

32

可以的。在手册中,您会找到这行文字:

git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
      [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]

所以在--之后,您需要输入文件或目录的路径。

例如:

git bisect start -- arch/i386 include/asm-i386

什么是“arch”? - Eduard
1
'arch/i386','include/asm-i386',我猜'b'isect正在操作的路径就是这些。它们是什么并不重要——Silvio只是用它们作为例子。根据上下文推测,'arch'是构建的'架构',在这种情况下是i386:https://en.wikipedia.org/wiki/Intel_80386。因此,在Silvio的情况下,进行bisect是因为需要找到一些i386构建中存在问题。 - knickum

1
Git bisect 允许你避免测试一个提交(参见手册中的“避免测试一个提交”):当你正在进行二分查找时,而 Git 已经为你选择了一个要测试的提交,你可以用 git reset --hard <commit you want> 来覆盖它的选择。
使用 git log,你可以找到最后一个影响文件(或子目录)的提交 - 这将返回它的哈希值。
git log -1 --pretty=format:%H -- path_that_you_are_interested_in

因此,每次git bisect建议您测试一个提交时,您应该运行此命令,以确保您只测试影响了somepath的提交:

git reset --hard $(git log -1 --pretty=format:%H -- somepath)

现在,我们还需要处理一件事情。如果在上次检查的良好提交和当前由git bisect选择的提交之间没有有趣的提交(即没有修改somepath的提交),我们可能会陷入循环。为了避免这种情况,我们应该使用一个条件子句:
#!/bin/bash

last_good=$(git bisect log | tail -1 | sed 's/git bisect good //')
last_interesting=$(git log -1 --pretty=format:%H -- lily/)

if [ "$last_good" == "$last_interesting" ]; then
    # there are no commits modifying somepath between previously
    # tested and currently checked-out one, so it must be good
    git bisect good
else 
    git reset --hard $(git log -1 --pretty=format:%H -- somepath)
fi

已更新以避免潜在的无限循环。 - Jan Warchoł
为什么不使用“git bisect skip”来标记没有更改疑似文件的提交,而将其视为良好的提交呢? - Jakub Narębski
这会不会更慢呢?我的解决方案是,即使 bisect 选择了一个不感兴趣的提交,我们也会立刻跳到最近的“有趣”提交。相反,如果总共有10000个提交,但只有10个提交是重要的,使用 skip 将意味着在访问这些“不重要”的提交时会浪费很多时间。 - Jan Warchoł

0
一种技术是创建一个从已知的良好位置开始的临时分支,然后简单地复制涉及该文件的所有提交 [即脚本],并在该临时分支上执行 bisect。这样,您就可以跳过所有不相关的提交。
这个问题在最近一个月左右的 Git 邮件列表中讨论过$gmane/232114。讨论没有确定一种易于预先跳过没有相关更改的提交的方法(可能有用 - 正如他们所说,欢迎补丁)。

但通常情况下,您无法获取仅包含更改某个文件的提交的分支,并且同时仍然有效。 - Jan Warchoł
我假设你所有的主线提交在提交时都是“好的”。你有哪些提交被认为是“好的”在提交时有指示吗?如果没有,那么你在编写修订遍历器以挑选出那些被认为是好的提交来进行二分查找时会遇到真正的问题。 - Philip Oakley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接