回归能稳定复现时,试试让 git bisect run 自动找提交

43 次浏览5 条回复

有个回归在几十个提交里找,手动来回切分支挺磨人。只要能写出一个返回退出码的检查脚本,Git 可以自己二分:

#!/usr/bin/env bash
npm test -- --runInBand test/parser.test.js >/dev/null 2>&1

保存成 check-regression.sh 后:

chmod +x check-regression.sh
git bisect start
git bisect bad HEAD
git bisect good <已知正常的提交>
git bisect run ./check-regression.sh
git bisect reset

环境:Git 2.x、Bash,以及项目本身可用的测试命令。脚本返回 0 表示该提交正常,1 到 124 表示有问题,125 表示跳过;测试依赖或外部服务不稳定时别硬让它判坏,先把环境固定住。git bisect run 结束后记得 git bisect reset 回到原分支。

这个用法很实用。补一个容易踩坑的点:测试依赖或服务启动失败时,最好让脚本返回 125 跳过,不然环境问题会被 bisect 当成某个提交引入的回归。还有,检查脚本尽量只依赖仓库里固定的测试入口,别让本机环境变量偷偷改变结果。

Nathan03Lv1#1

这个用法很实用。补一个容易踩坑的点:测试依赖或服务启动失败时,最好让脚本返回 125 跳过,不然环境问题会被 bisect 当成某个提交引入的回归。还有,检查脚本尽量只依赖仓库里固定的测试入口,别让本机环境变量偷偷改变结果。

还有个前置条件:bisect 会反复切换提交,工作区最好先保持干净,未提交改动可以 stash 或另开 worktree,不然切换失败或把当前改动带进每次测试,结果会失真。若每个提交都要重装依赖,也要把环境重建过程固定下来;找到首个坏提交后留着 git bisect log,复盘时能看出哪些提交被判定或跳过了。

隔壁空白Lv1#2

还有个前置条件:bisect 会反复切换提交,工作区最好先保持干净,未提交改动可以 stash 或另开 worktree,不然切换失败或把当前改动带进每次测试,结果会失真。若每个提交都要重装依赖,也要把环境重建过程固定下来;找到首个坏提交后留着 git bisect log,复盘时能看出哪些提交被判定或跳过了。

再补一个状态污染的问题:检查脚本如果会生成缓存、构建产物或启动临时服务,最好在每次运行前后清掉,或者放到独立临时目录里。bisect 会反复复用工作区,上一提交留下的文件可能让下一提交“误判”。尤其是增量构建,必要时宁可先做一次干净构建再跑测试。

还有个小细节:检查脚本里如果有清理逻辑,别让最后一个 rm 或停止临时服务的命令覆盖测试退出码。可以先保存状态,再清理,最后 exit "$status"。不然测试已经失败,脚本却返回 0,bisect 会把坏提交判成 good。

MukiLv1#4

还有个小细节:检查脚本里如果有清理逻辑,别让最后一个 rm 或停止临时服务的命令覆盖测试退出码。可以先保存状态,再清理,最后 exit "$status"。不然测试已经失败,脚本却返回 0,bisect 会把坏提交判成 good。

对,清理逻辑最好和测试结果分开处理。脚本如果开了 set -e,测试失败可能还没走到清理就提前退出;可以把测试放进 if ...; then status=0; else status=$?; fi,清理完成后再按约定返回 status,只有依赖或服务没准备好时才返回 125。这样既不会吞掉真实失败,也不会把环境故障误判成回归。