git bisect 本身不自动找bug,只高效缩小范围;结果准确性取决于good/bad标记是否准确、测试是否稳定、跳过操作是否合理。

git bisect 不是自动找 Bug 的魔法,它只负责高效缩范围;真正决定结果对错的,是你标得准不准、测得稳不稳、跳得对不对。
怎么启动并设置 good/bad 范围才不会翻车
启动本身很简单,但标错 good 或 bad 会直接让整个过程收敛到错误提交。常见翻车点包括:
- 把“没触发 Bug”当成“逻辑正确”——比如某个
good提交只是恰好没跑那条分支,实际已有隐患 - 用了一个 unstable 的 tag(如
v1.2.0-rc2)当good,结果它本身就有未合入的修复 - 没确认当前
HEAD真的有 Bug:可能只是本地环境没装依赖、配置漏了、缓存没清
实操建议:
- 先手动复现 Bug,再执行
git bisect start -
git bisect bad后立刻加一句git bisect good v1.0(别只写v1,避免歧义) - 如果不确定哪个旧版本绝对 OK,就往前多试一两个 tag,比如从
v0.9.0开始,再比对v1.0.0
git bisect run 自动化时脚本必须满足什么条件
git bisect run 是提速关键,但脚本稍有不慎就会让 Git 误判。它只看退出码:0 = good,非 0 = bad。
- 脚本里不能有
read、vim、echo后等待输入等交互操作 - 不能依赖未
git add的本地修改(bisect 切换时这些会丢失) - 编译失败、import 报错、HTTP 请求超时都应返回非
0(比如exit 1),否则 Git 会当成good - 推荐在脚本开头加
set -e,保证任意命令失败就中断并返回非0
一个最小可用示例(test-bug.sh):
#!/bin/sh set -e npm ci --silent npm run build python -m pytest tests/test_auth.py -v --tb=short
然后运行:git bisect run ./test-bug.sh
遇到编译失败或 merge 提交该怎么跳过
不是所有中间提交都能跑通测试。Git 默认卡住,你得主动干预:
- 编译失败 / 缺少依赖 / 配置缺失 → 用
git bisect skip,可连续执行多次 - 遇到 merge 提交(
git show --pretty=%p -q HEAD输出两个哈希)→ 默认会随机选一边,容易绕远。若项目走主干开发,加--first-parent启动:git bisect start --first-parent - 跳太多次后范围太散?用
git bisect visualize看当前剩余候选集,必要时用git bisect reset重来,并显式指定新范围:git bisect start abc123 bad456
中途想暂停或恢复,BISECT_LOG 怎么用
git bisect reset 会清掉状态,但日志还在:.git/BISECT_LOG 里每行都是你输过的 git bisect good 或 git bisect bad。
- 想备份进度:
git bisect log > bisect-backup.txt - 想快速定位最后标记的
bad提交:tail -n 1 .git/BISECT_LOG | grep 'bad ' - 恢复时别直接
git bisect start,先查出最新确认的good和bad哈希,再显式启动:git bisect start <bad-hash><good-hash></good-hash></bad-hash>
真正容易被忽略的是:merge 提交的父链选择、skip 后剩余范围是否仍连贯、以及脚本里任何没 set -e 的静默失败——这些地方不出问题则已,一出就是半天白忙。











