Git Bisect 二分法定位引入 Bug 的提交
"这个功能昨天还好好的"——一千个提交里到底哪一条搞坏的?
二分查找:每次挑中间那条试,好的扔一半、坏的扔一半,10 次左右就能从 1000 条锁定到 1 条。
一、手动流程
git bisect start
git bisect bad # 当前版本有问题
git bisect good v1.2.0 # 这个 tag 是好的
# Git 检出中间那条,你测一下
# 有问题:
git bisect bad
# 没问题:
git bisect good
# 直到输出 "<hash> is the first bad commit"
git bisect reset # 回到原来的分支
每一步 Git 都会告诉你还剩几个提交、大约还要几步。
二、自动化:交给脚本
有能自动判断的测试,就不用手测:
git bisect start HEAD v1.2.0
git bisect run ./scripts/check.sh
check.sh 的退出码决定结果:
0:好1~127(除 125):坏125:这条跳过(比如编译不过、环境不具备)
#!/usr/bin/env bash
yarn install --silent || exit 125
yarn test --runInBand || exit 1
三、跳过测不了的提交
中间某条提交依赖的包已经下不到了,或者编译直接失败,别硬判成 bad,那会把范围带偏:
git bisect skip
四、排查思路
- 测试要快:bisect 会跑 log2(n) 次,单次 10 分钟就是几小时
- 测试要准:脚本必须只在"这个 bug 在不在"上判定,别掺进其他失败
- 范围要干净:
good挑最近的已知正常点,跨太远反而慢 - 别在脏工作区跑:
git status必须干净,否则检出被拦
五、bisect 结束之后
git show <first-bad-commit>
看它改了什么、谁提交的、有没有关联 PR。通常答案一目了然。
修完之后记得 git bisect reset,否则仓库会一直停在 detached HEAD 上。
六、什么时候用它
- 回归型 bug,有明确"以前是好的"版本
- 有条件跑一个自动判定脚本
- 提交历史相对线性(merge 很多时二分照样能用,但边界会更绕)
如果连"什么是好"都定义不了,bisect 帮不上忙,老老实实看日志更快。