历史提交很多时,逐个检查成本高。只要能稳定判断好坏,就可以用二分缩小范围。
本文使用Git 2.x 与独立演示仓库。Git(分布式版本管理)保存提交对象和引用,工作区、暂存区与提交历史不是同一份状态。每次操作先判断它改变哪个区域,再决定是否适合当前协作情境。
1. 从现象推到机制
bisect 在已知正常与已知异常之间选择中间提交,根据判断排除一半区间。判定规则必须稳定且与环境变化解耦。某个版本无法构建时应区分不可判定,不要误报为业务失败。
图中的四个节点分别表示已知边界、中间版本、稳定复现、原因分析。顺着实线检查输入如何变成输出,再沿虚线核对反馈条件。图示表达的是本文讨论的关系,不是实测曲线或现场截图。
2. 最小实现与输入条件
先准备一个只检查该缺陷的小脚本,固定数据与依赖。每次切换提交后重新生成必要产物,结束时恢复原分支状态。
1
2
3
4
5
git bisect start
git bisect bad <bad_commit>
git bisect good <good_commit>
# 每轮复现后执行 git bisect good 或 bad
git bisect reset
示例在没有私人资料的临时仓库执行。先看 status、diff 与 log,再运行改变状态的命令;共享历史优先新增提交表达修复,不用改写历史掩盖已经发生的变化。
3. 用对照区分原因
下表列出需要主动改变的条件。预期行为来自机制分析,复现时还需记录运行环境和原始输出,不能将预期当作已经测得的结果。
| 改变的条件 | 需要验证的行为 |
|---|---|
| 复现规则随机失败 | 二分结论可能被误导 |
| 旧提交依赖不再可用 | 需要标为无法判断或修复环境 |
| 定位到首个异常提交 | 还需理解它如何改变行为 |
对照 1:复现规则随机失败
二分结论可能被误导。观察时记录相同提交的重复判定。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
对照 2:旧提交依赖不再可用
需要标为无法判断或修复环境。观察时记录构建失败与缺陷现象区别。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
对照 3:定位到首个异常提交
还需理解它如何改变行为。观察时记录该提交实际差异与机制。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
4. 适用条件与取舍
找到引入问题的提交不代表责任归因。需求变更、数据变化和后续依赖也可能参与,修复要围绕行为与证据。
一次正常运行只覆盖了这组输入。继续扩展前,应把上面的异常对照保留下来,尤其关注“定位到首个异常提交”这一分支。后续方案若改变了图中任意一处依赖,原来的判断就要重新验证,不能仅凭界面相似或返回值相同沿用结论。