我读过一些文章,说git平分很棒。然而,我不明白为什么它很棒。
有人能演示一些代码示例:
如何使用它? 就像责备一样吗?
我读过一些文章,说git平分很棒。然而,我不明白为什么它很棒。
有人能演示一些代码示例:
如何使用它? 就像责备一样吗?
当前回答
$ git平分…基本上是一个Git调试工具。'Git Bisect'通过检查上次(已知的)工作提交后的前一次提交来调试。它使用二分搜索遍历所有提交,找到引入回归/错误的提交。
$ git bisect start #开始平分
$ git bisect bad #表示当前提交(v1.5)有回归/设置“坏”点
$ git bisect good v1.0 #提到它的最后一个良好的工作提交(没有回归)
这里提到的“坏”和“好”点将帮助git平分(二分搜索)选择中间的元素(提交v1.3)。如果回归是在提交v1.3,你将把它设置为新的“坏”点,即(好-> v1.0和坏-> v1.3)
$ git bisect bad
或者类似地,如果提交v1.3没有bug,你将把它设置为新的“Good point”,即(*Good -> v1.3和Bad -> v1.6)。
$ git bisect good
其他回答
Git平分运行自动平分
如果你有一个自动的。/test脚本,如果测试正常,退出状态为0,你可以用bisect run自动找到bug:
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
当然,这假设如果测试脚本./test被git跟踪,那么它不会在平分期间的某个早期提交中消失。
我经常发现,你可以通过从树中复制树内脚本,并可能使用类似path的变量,然后从那里运行它来解决问题。
当然,如果测试所依赖的测试基础设施破坏了旧的提交,那么就没有解决方案,您将不得不手动操作,决定如何逐个测试提交。
然而,我发现使用这种自动化通常是有效的,并且可以为您的任务积压中较慢的测试节省大量时间,在那里您可以让它运行一夜,并且可能在第二天早上发现您的错误,这值得一试。
更多的建议
在平分后,保持在第一个失败的提交上,而不是回到master:
git bisect reset HEAD
开始+最初的坏和好的一气呵成:
git bisect start KNOWN_BAD_COMMIT KNOWN_GOOD_COMMIT~
等于:
git checkout KNOWN_BAD_COMMIT
git bisect start
git bisect bad
git bisect good KNOWN_GOOD_COMMIT
看看到目前为止已经测试了什么(通过手动测试或运行):
git bisect log
样例输出:
git bisect log
git bisect start
# bad: [00b9fcdbe7e7d2579f212b51342f4d605e53253d] 9
git bisect bad 00b9fcdbe7e7d2579f212b51342f4d605e53253d
# good: [db7ec3d602db2d994fe981c0da55b7b85ca62566] 0
git bisect good db7ec3d602db2d994fe981c0da55b7b85ca62566
# good: [2461cd8ce8d3d1367ddb036c8f715c7b896397a5] 4
git bisect good 2461cd8ce8d3d1367ddb036c8f715c7b896397a5
# good: [8fbab5a3b44fd469a2da3830dac5c4c1358a87a0] 6
git bisect good 8fbab5a3b44fd469a2da3830dac5c4c1358a87a0
# bad: [dd2c05e71c246f9bcbd2fbe81deabf826c54be23] 8
git bisect bad dd2c05e71c246f9bcbd2fbe81deabf826c54be23
# bad: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05] 7
git bisect bad c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05
# first bad commit: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c0
在git日志上显示好的和坏的参考,以获得更好的时间概念:
git log --decorate --pretty=fuller --simplify-by-decoration master
这只显示带有相应引用的提交,这大大降低了噪音,但确实包括自动生成的引用类型:
refs/bisect/good*
refs/bisect/bad*
它告诉我们哪些提交被标记为好或坏。
如果您想使用这个命令,可以考虑使用这个测试回购。
失败来得快,成功来得慢
有时:
失败发生得很快,例如,第一个测试中断了 成功需要一段时间,例如,失败的测试通过了,所有其他我们不关心的测试都随之而来
对于这些情况,例如,假设失败总是发生在5秒内,如果我们懒得让测试更具体,我们应该这样做,我们可以使用超时:
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
这是因为timeout退出124,而test-command失败退出1。
神奇的退出状态
Git bisect运行对退出状态有点挑剔:
任何大于127的值都将导致等分失败,如下所示: Git平分运行失败: 退出代码134从…/test -aa' < 0或>= 128 特别是,C断言(0)会导致SIGABRT并以状态134退出,非常烦人。 125是魔法,使运行被跳过与git平分跳过。 这样做的目的是帮助跳过由于不相关的原因而损坏的构建。
详见man git-bisect。
所以你可能想要使用这样的东西:
#!/usr/bin/env bash
set -eu
./build
status=0
./actual-test-command || status=$?
if [ "$status" -eq 125 ] || [ "$status" -gt 127 ]; then
status=1
fi
exit "$status"
在git 2.16.1上测试。
$ git平分…基本上是一个Git调试工具。'Git Bisect'通过检查上次(已知的)工作提交后的前一次提交来调试。它使用二分搜索遍历所有提交,找到引入回归/错误的提交。
$ git bisect start #开始平分
$ git bisect bad #表示当前提交(v1.5)有回归/设置“坏”点
$ git bisect good v1.0 #提到它的最后一个良好的工作提交(没有回归)
这里提到的“坏”和“好”点将帮助git平分(二分搜索)选择中间的元素(提交v1.3)。如果回归是在提交v1.3,你将把它设置为新的“坏”点,即(好-> v1.0和坏-> v1.3)
$ git bisect bad
或者类似地,如果提交v1.3没有bug,你将把它设置为新的“Good point”,即(*Good -> v1.3和Bad -> v1.6)。
$ git bisect good
git bisect背后的思想是在历史中执行二进制搜索以找到特定的回归。假设您拥有以下开发历史:
... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current
您知道您的程序在当前的修订版本中不能正常工作,它在修订版本0时工作。因此,回归很可能是在当前的1、2、3、4、5次提交中引入的。
你可以试着检查每个提交,构建它,检查回归是否存在。如果有大量的提交,这可能会花费很长时间。这是线性搜索。我们可以用二分法搜索。这就是git bisect命令的作用。在每一步中,它都试图将有潜在缺陷的修订数量减少一半。
你会像这样使用命令:
$ 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将检出提交。在我们的例子中,它是commit 3。您需要构建您的程序,并检查回归是否存在。你还需要告诉git这个修订的状态,如果回归存在,git平分为坏,如果没有,git平分为好。
让我们假设在提交4中引入了回归。然后回归在这个修订中不存在,我们告诉它git。
$ make
$ make test
... ... ...
$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[< ... sha ... >] 5
然后它将检出另一个提交。4或5(因为只有两次提交)。假设它选了5。在构建之后,我们测试程序并查看回归是否存在。然后我们告诉它git:
$ make
$ make test
... ... ...
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[< ... sha ... >] 4
我们测试最后的版本4。因为它是引入回归的那个,我们告诉它git:
$ make
$ make test
... ... ...
$ git bisect bad
< ... sha ... > is the first bad commit
< ... commit message ... >
在这种简单的情况下,我们只需要测试3个版本(3,4,5),而不是4个版本(1,2,3,4)。这是一个小胜利,但这是因为我们的历史是如此之小。如果搜索范围是N个提交,我们应该期望用git平分测试1 + log2n个提交,而不是用线性搜索粗略地测试N / 2个提交。
一旦找到了引入回归的提交,就可以研究它以找到问题所在。完成后,使用git bisect reset将所有内容恢复到使用git bisect命令之前的原始状态。
再补充一点:
我们可以为git bisect start指定一个文件名或路径,以防我们知道bug来自特定的文件。 例如, 假设我们知道导致回归的更改在com/workingDir中 然后运行git bisect start / workingdir 只有修改了此目录内容的提交才会被检查 这让事情变得更快。
此外,如果很难判断一个特定的提交是好是坏,您可以使用 可以运行git的等分跳过,这将忽略它。考虑到有足够多的其他 提交时,git bisect将使用另一个来缩小搜索范围。
博士TL;
开始:
$ git bisect start
$ git bisect bad
$ git bisect good <goodcommit>
Or
$ git bisect start
$ git bisect good
$ git bisect bad <badcommit>
平分:在此之后留下X个修订进行测试(大约Y步)
重复一遍:
问题还存在吗?
是的:$ git平分坏 不:$ git平分好
结果:
<abcdef> is the first bad commit
当完成:
git bisect reset