$ git stash save
$ git bisect start
$ git bisect bad
$ git bisect good 0
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[< ... sha ... >] 3
git checkout KNOWN_BAD_COMMIT
git bisect start
# Confirm that our test script is correct, and fails on the bad commit.
./test
# Should output != 0.
echo $?
# Tell Git that the current commit is bad.
git bisect bad
# Same for a known good commit in the past.
git checkout KNOWN_GOOD_COMMIT
./test
# Should output 0.
echo $?
# After this, git automatically checks out to the commit
# in the middle of KNOWN_BAD_COMMIT and KNOWN_GOOD_COMMIT.
git bisect good
# Bisect automatically all the way to the first bad or last good rev.
git bisect run ./test
# End the bisect operation and checkout to master again.
git bisect reset
7条答案
按热度按时间ktca8awb1#
git bisect
背后的想法是在历史中执行二进制搜索以找到特定的回归。假设您有以下开发历史:字符串
你知道你的程序在
current
版本下不能正常工作,而在0
版本下工作。所以回归可能是在1
,2
,3
,4
,5
,current
中的一个提交中引入的。你可以尝试检查每个提交,构建它,检查是否存在回归。如果有大量的提交,这可能需要很长时间。这是一个线性搜索。我们可以通过二进制搜索做得更好。这就是
git bisect
命令所做的。在每一步,它都会尝试将潜在错误的修订数量减少一半。您将像这样使用命令:
型
在这个命令之后,
git
将 checkout 一个提交。在我们的例子中,它将是commit3
。你需要构建你的程序,并检查回归是否存在。你还需要告诉git
这个版本的状态,如果回归存在,就用git bisect bad
,如果不存在,就用git bisect good
。让我们假设回归是在提交
4
中引入的,那么回归在这个版本中不存在,我们告诉git
。型
然后,它将检出另一个提交。
4
或5
(因为只有两个提交)。让我们假设它选择了5
。在构建之后,我们测试程序,看看回归是否存在。然后我们告诉git
:型
我们测试最后一个版本
4
。由于它是引入回归的版本,我们告诉它git
:型
在这种简单的情况下,我们只需要测试3个版本(
3
,4
,5
)而不是4(1
,2
,3
,4
).这是一个小的胜利,但这是因为我们的历史是如此之小.如果搜索范围是N提交,我们应该期望用git bisect
测试1 + log 2 N次提交,而不是用线性搜索测试大约N / 2次提交。一旦你找到了引入回归的提交,你可以研究它来找到问题所在。一旦完成了,你可以在使用
git bisect
命令之前使用git bisect reset
将所有东西恢复到原始状态。uurity8g2#
git bisect run
自动二分法如果你有一个自动化的
./test
脚本,如果测试是OK,它的退出状态为0,你可以用bisect run
自动找到bug:字符串
当然,这是假设测试脚本
./test
被git跟踪,它不会在二分法的早期提交中消失。我发现,通常你可以通过将树内脚本从树中复制出来,并可能使用类似
PATH
的变量,然后从那里运行它。当然,如果
test
所依赖的测试基础设施在较早的提交上出现故障,那么就没有解决方案了,您将不得不手动操作,决定如何逐个测试提交。然而,我发现使用这种自动化通常是有效的,并且可以节省大量的时间,因为你可以让它在一夜之间运行,并且可能在第二天早上发现你的bug,这是值得一试的。
更多提示
在bisect之后停留在第一次失败的提交上,而不是回到
master
:型
start
+初始bad
和good
一次性完成:型
是相同的:
型
查看到目前为止测试的内容(通过手动
good
和bad
或run
):型
示例输出:
型
在git log上显示好的和坏的refs,以获得更好的时间概念:
型
这只显示了带有相应ref的提交,这大大减少了噪音,但确实包括自动生成的ref类型:
型
它告诉我们哪些提交被标记为好或坏。
如果您想使用这个命令,请考虑this test repo。
失败来得快,成功来得慢
有时:
对于这些情况,例如,假设失败总是在5秒内发生,如果我们懒得让测试更具体,我们可以使用
timeout
:型
这是因为
timeout
退出124
,而test-command
的失败退出1
。Magic退出状态
git bisect run
对退出状态有点挑剔:型
特别是,C
assert(0)
导致SIGABRT
并以状态134退出,非常烦人。git bisect skip
。这样做的目的是帮助跳过由于不相关的原因而损坏的构建。
详情请参见
man git-bisect
。所以你可能想使用类似这样的东西:
型
在git 2.16.1上测试。
92vpleto3#
TL;DR
开始:
字符串
或
型
第一个月
重复:
问题仍然存在吗?
$ git bisect bad
$ git bisect good
结果:
型
完成后:
型
vhipe2zx4#
再补充一点:
我们可以指定一个文件名或路径到
git bisect start
,以防我们知道bug来自特定的文件。例如,假设我们知道导致回归的更改在com/workingDir目录中,那么我们可以运行git bisect start com/workingDir
这意味着只有更改该目录内容的提交才会被检查,这使得事情变得更快。另外,如果很难判断某个提交是好是坏,你可以运行
git bisect skip
,它会忽略它。如果有足够多的其他提交,git bisect会使用另一个来缩小搜索范围。uhry853o5#
$ git bisect ..
基本上是一个 * 用于调试的Git工具 *。'Git Bisect'通过检查自上次(已知)工作提交以来的前提交来进行调试。它使用二进制搜索来检查所有这些提交,以找到引入回归/bug的提交。$ git bisect start
#开始平分$ git bisect bad
#说明当前提交(v1.5)具有回归/设置“坏”点$ git bisect good v1.0
#提到它的最后一个良好的工作提交(没有回归)这里提到的“bad”和“good”点将帮助git bisect(二进制搜索)选择中间的元素(commit v1.3)。如果在commit v1.3时回归在那里,你将把它设置为新的“bad”点,即(Good -> v1.0 and Bad -> v1.3)
字符串
或者类似地,如果commit v1.3没有bug,你将把它设置为新的“Good point”,即(*Good -> v1.3 and Bad -> v1.6)。
型
brgchamk6#
注意:术语
good
和bad
并不是唯一可以用来标记带有或不带有某个属性的提交的术语。Git 2.7(Q4 2015)引入了新的
git bisect
选项。字符串
文件增加:
有时候,你并不是在寻找引入了中断的提交,而是在寻找一个导致了其他“旧”状态和“新”状态之间的变化的提交。
例如,您可能正在查找引入特定修复的提交。
或者,您可能正在寻找源代码文件名最终全部转换为公司命名标准的第一次提交。
在这种情况下,使用“好”和“坏”来指“变更前的状态”和“变更后的状态”可能会非常混乱。
因此,您可以分别使用术语“
old
“和“new
“来代替“good
“和“bad
“。(But请注意,您不能在单个会话中混合“
good
“和“bad
“与“old
“和“new
“。在这种更一般的用法中,您为
git bisect
提供了一个“new
“提交,该提交具有某些属性,而“old
“提交则没有该属性。每次
git bisect
checkout 一个提交时,您都要测试该提交是否具有以下属性:如果是,则将提交标记为“
new
“;否则,将其标记为“old
“。当二分法完成后,
git bisect
将报告哪个提交引入了该属性。参见commit 06e6a74,commit 21b55e3,commit fe67687(2015年6月29日)by Matthieu Moy (
moy
)。commit 21e5cfd(2015年6月29日)Antoine Delaite (
CanardChouChinois
)。(由Junio C Hamano --
gitster
--合并于commit 22dd6eb,2015年10月5日)确保使用Git 2.39(Q4 2022)for
git bisect run
:它包括修复bisect-helper
中的回归,该回归错误地将给'git bisect run
'(man)的命令的参数视为帮助程序的参数。参见commit e9011b6,commit 464ce0a,commit 58786d7(2022年11月10日)by Đoàn Trần Công Danh (
sgn
)。(由Junio C Hamano --
gitster
--合并于commit e3d40fb,2022年11月23日)bisect--helper
:使用OPT_SUBCOMMAND
解析子命令报告人:LukáDoktor
签字人:oàn Tr n ng Danh
签名人:Taylor Blau
目前,我们正在使用
OPT_CMDMODE,
解析子命令,即使找到了命令,它也会继续解析更多选项。当我们运行“
git bisect run
“(man)时,命令需要一个--log
或--no-log
参数,或者其中一个“--bisect-...
“参数,bisect--helper
可能会错误地认为这些选项是bisect--helper
的选项。我们可以通过在从
git-bisect.sh
调用时传递“--
“来解决这些问题,并在bisect--helper
中跳过“--
“。但是,它可能会干扰用户的“
--
”。让我们使用
OPT_SUBCOMMAND
解析子命令,因为该API是为这个特定用例而生的。mbzjlibv7#
git对分退出状态
Ciro Santilli的2014 answer将其称为“神奇退出状态”
它们在Git 2.36(Q2 2022)中的使用方式略有不同:一个不太常见的错误是编写一个脚本以feed“
git bisect
“(man)运行,而没有使其可执行,在这种情况下,所有测试都将退出,并返回126或127个错误代码,即使是在标记为良好的修订版上。尝试识别这种情况并尽早停止迭代。
参见René Scharfe (
rscharfe
)的commit 48af1fd、commit ba5bb81、commit 8efa2ac、commit 80c2e96(2022年1月18日)。(由Junio C Hamano --
gitster
--合并于commit e828747,2022年3月6日)bisect--helper
:在退出代码为126和127时,请仔细检查运行命令签核人:René Scharfe
当运行命令无法执行或无法找到时,shell分别返回退出代码126或127。
由于历史原因,有效的运行命令也可以返回这些代码,以指示错误的修订。
这意味着错别字可能会导致在整个距离上进行虚假的平分运行,并最终报告无效结果。
最好的解决方案是保留退出代码126和127,就像71b0251(Bisect run:,2007-10-26,Git v1.5.4-rc 0--merge)(Bisect run:“skip”current commit if script exit code is 125.,2007-10-26)对125所做的那样,并在我们得到它们时中止
bisect run
。不过,对于那些依赖于文档说明126和127可以用于糟糕的修订的人来说,这可能是不方便的。
此修补程序使用的解决方法是在已知良好的修订版上运行该命令,如果仍然得到相同的错误代码,则中止。
这将为使用退出代码126和127的脚本的运行增加一个步骤,但仍支持它们,但有一个例外:它不适用于无法识别(手动标记的)已知良好版本的命令。
使用低退出代码的运行命令不受影响。
在执行缺失命令两次和三次检出(第一步、已知良好的修订版和返回第一步的修订版)后,会报告拼写错误。
请参见examples。