如何使用git对分?
我读过一些文章说,如何使用git对分?,git,git-bisect,Git,Git Bisect,我读过一些文章说,git-bisect非常棒。然而,我不是以英语为母语的人,我不明白为什么它很棒 请有人用一些代码示例演示一下: 如何使用它 这就像是svn的过错吗 git-bisect背后的思想是在历史中执行二进制搜索以找到特定的回归。假设您有以下开发历史: ... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current 您知道您的程序在当前版本下工作不正常,并且在0版本下工作。因此,回归很可能是在一个提交中引入的1,2,3,4,5,current
git-bisect
非常棒。然而,我不是以英语为母语的人,我不明白为什么它很棒
请有人用一些代码示例演示一下:
git-bisect
背后的思想是在历史中执行二进制搜索以找到特定的回归。假设您有以下开发历史:
... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current
您知道您的程序在当前
版本下工作不正常,并且在0
版本下工作。因此,回归很可能是在一个提交中引入的1
,2
,3
,4
,5
,current
您可以尝试签出每个提交,构建它,检查回归是否存在。如果有大量提交,这可能需要很长时间。这是一个线性搜索。我们可以通过二进制搜索做得更好。这就是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
然后它将签出另一个提交。4
或5
(因为只有两次提交)。假设它选择了5
。构建之后,我们测试程序,并查看回归是否存在。然后我们告诉它到git:
$ make
$ make test
... ... ...
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[< ... sha ... >] 4
$ 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-bisect
测试1+log2n个提交,而不是使用线性搜索测试大约N/2个提交
一旦找到了引入回归的提交,就可以研究它来发现问题。完成此操作后,在使用
git bisect
命令之前,您可以使用git bisect reset
将所有内容恢复到原始状态。$git bisect..
基本上是一个用于调试的git工具。”Git Bisect通过执行上次(已知)工作提交后的上一次提交进行调试。它使用二进制搜索遍历所有这些提交,以找到引入回归/错误的提交
$git对分开始
#开始对分
$git bisect bad
#说明当前提交(v1.5)具有回归/设置“bad”点
$git bisect good v1.0
#提到它是最后一次良好的工作提交(无回归)
提到“坏”和“好”点将有助于git对分(二进制搜索)选择中间元素(commit v1.3)。如果在提交v1.3时存在回归,则将其设置为新的“坏”点,即(好->v1.0和坏->v1.3)
或者类似地,如果commit v1.3没有bug,则将其设置为新的“Good point”,即(*Good->v1.3和Bad->v1.6)
git对分运行
自动对分
如果您有一个自动的/test
脚本,如果测试正常,该脚本的退出状态为0,则您可以通过对分运行
自动找到错误:
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
git bisect log
当然,这假设如果测试脚本/test
是git跟踪的,那么它不会在平分期间的某个早期提交中消失
我发现,通常只需将树内脚本从树中复制出来,并可能使用类似于PATH
的变量,然后从那里运行它,就可以摆脱这种情况
当然,如果test
所依赖的测试基础结构依赖于较旧的提交,则没有解决方案,您将不得不手动执行操作,决定如何逐个测试提交
然而,我发现使用这种自动化通常是有效的,并且可以为积压的任务中较慢的测试节省大量时间,您可以让它在一夜之间运行,并且可能在第二天早上发现您的bug,这是值得尝试的
更多提示
在对分后继续执行第一次失败的提交,而不是返回到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 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
这仅显示具有相应ref的提交,这将灰色地减少噪波,但不包括以下类型的自动生成ref:
refs/bisect/good*
refs/bisect/bad*
它告诉我们哪些承诺被标记为好的或坏的
考虑是否要使用该命令
失败是快的,成功是慢的
有时:
- 故障发生得很快,例如,第一次测试中的一次中断
- 成功需要一段时间,例如,失败的测试通过,而我们不关心的所有其他测试都会跟进
timeout
,如下所示:
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
这是因为timeout
退出124
,而测试命令的失败退出1
魔法退出状态
git bisect run
对退出状态有点挑剔:
- 高于127的任何值都会导致平分失败,如下所示:
git bisect run failed:
exit code 134 from '../test -aa' is < 0 or >= 128
#!/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 bisect start
,以防我们知道bug来自特定的文件。
例如
假设我们知道导致回归的更改在com/workingDir中
然后我们可以运行git bisect start com/workingDir
这意味着
在…上
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
git bisect run failed:
exit code 134 from '../test -aa' is < 0 or >= 128
#!/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 bisect start
$ git bisect bad
$ git bisect good <goodcommit>
$ git bisect start
$ git bisect good
$ git bisect bad <badcommit>
<abcdef> is the first bad commit
git bisect reset
git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]