回归问题可以用 git bisect run 自动缩小范围

47 次浏览4 条回复

如果能写一个失败时返回非 0 的小脚本,定位是哪次提交引入回归时可以让 Git 自动二分:

git bisect start
git bisect bad HEAD
git bisect good v1.2.0
git bisect run ./scripts/check-regression.sh

check-regression.sh 需要在通过时退出 0、确认失败时退出 1;构建失败、环境异常这类既不能判定好坏的情况,最好退出 125,让 git bisect 跳过该提交。脚本里可以先执行固定的测试命令,例如 go test ./... 或 pytest -q tests/test_login.py,但要保证依赖和测试数据可重复。结束后用 git bisect reset 回到原分支。环境:Git 2.25+;只适合工作区能自动构建和验证的回归问题。

这里有个容易踩的点:git bisect run 对退出码的判断不只是 0/1。0 表示 good,1 到 124 通常会当成 bad,125 才是跳过当前提交;脚本里最好把依赖下载失败、服务没启动这类环境异常明确返回 125,不然可能把环境问题误判成回归。最后别忘了 git bisect reset。

我还会把脚本的可重复性放在前面:每次切到一个提交后,尽量清掉上一次留下的构建产物或临时测试数据,再执行检查。尤其是增量构建、共享数据库这类状态,很容易让后面的提交“继承”前面的结果,二分出来的位置就不一定可信。脚本如果需要准备环境,最好把准备步骤也写进去,并在失败时区分测试失败和环境没准备好。

还有一个实用细节:如果回归测试本身会偶发失败,别让一次随机失败直接决定二分结果。可以在脚本里对关键断言重试几次;仍然无法判断时返回 125 跳过当前提交,并把失败日志单独保存。这样定位结果会比把 flaky 当成确定性 bad 更可信。

再补个退出码边界:脚本返回 125 才是跳过当前提交;如果返回 126 或 127,通常表示命令不可执行或找不到,git bisect run 可能直接中止,而不是把它当成 bad。CI 里可以先检查测试命令是否存在,环境问题统一转成 125,并把原始日志保留下来。