Skip to content

二分查找(Bisect)

git bisect 使用二分查找算法,帮助你快速定位哪次提交引入了 bug。在有数百次提交的项目中,这比逐个检查效率高得多。

git bisect start / good / bad

bash
# 1. 启动二分查找
git bisect start

# 2. 标记当前版本为"坏"(有 bug)
git bisect bad
# 或者指定已知的坏提交
git bisect bad HEAD

# 3. 标记某个已知正常的版本为"好"
git bisect good v1.0.0       # 使用标签
git bisect good abc123       # 使用 SHA-1
git bisect good HEAD~100     # 往前 100 个提交

Git 会自动检出两者中间的提交,你需要测试并告诉 Git 这是好还是坏:

bash
# 测试当前版本...

# 如果是好的
git bisect good

# 如果是坏的
git bisect bad

Git 自动缩小范围,重复这个过程,直到找到第一个坏提交。

手动二分查找过程示例

bash
# 有 100 个提交要检查
git bisect start
git bisect bad HEAD       # 最新版本有 bug
git bisect good v1.0.0    # v1.0.0 是正常的

# 第1次,Git 检出第 50 个提交
# Bisecting: 50 revisions left to test after this (roughly 6 steps)
# [abc50] commit message at 50

# 测试...发现有 bug
git bisect bad

# 第2次,Git 检出第 25 个提交
# Bisecting: 25 revisions left to test after this (roughly 5 steps)
# [abc25] commit message at 25

# 测试...发现正常
git bisect good

# 第3次,Git 检出第 37 个提交...
# 继续这个过程,大约 7 次就能在 100 个提交中找到目标

找到后的输出:

abc37 is the first bad commit
commit abc37...
Author: ...
Date: ...

    feat: 修改了某个逻辑

git bisect run 自动化二分查找

如果有自动化测试,可以用脚本替代手动测试:

bash
# 使用测试脚本自动化二分查找
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
git bisect run npm test    # 脚本退出码 0 = good,非0 = bad

# 使用自定义脚本
cat > test-bug.sh << 'EOF'
#!/bin/bash
# 测试特定功能
node -e "const app = require('./src/app'); if (app.calculate(2, 3) !== 5) process.exit(1)"
EOF
chmod +x test-bug.sh
git bisect run ./test-bug.sh

run 命令会根据脚本的退出码自动判断:

  • 退出码 0:当前提交是"好的"
  • 退出码 1-127(除125):当前提交是"坏的"
  • 退出码 125:跳过此提交(如测试无法运行)

git bisect log / reset

bash
# 查看 bisect 的操作日志
git bisect log
# git bisect start
# git bisect bad HEAD
# git bisect good v1.0.0
# git bisect good abc50
# ...

# 导出日志,以便重放
git bisect log > bisect.log
git bisect replay bisect.log    # 重放日志(恢复 bisect 状态)

# 结束 bisect,回到原来的分支
git bisect reset
# Bisecting done. HEAD is now at original commit.

实战案例:快速定位 Bug 提交

bash
# 场景:发现用户反馈某个功能在最新版出现问题
# 已知:v2.0.0 正常,当前版本(v2.3.5)有问题

# 1. 启动二分查找
git bisect start
git bisect bad v2.3.5     # 或 HEAD
git bisect good v2.0.0

# Git 提示:大约需要 8 步(在 150 个提交中)

# 2. 对每个检出的版本运行测试
# (如果有自动化测试,用 bisect run)
git bisect run ./scripts/test-feature.sh

# 3. 找到问题提交
# abc123 is the first bad commit
# Author: Dev <dev@company.com>
# Date: ...
# refactor: 重构了订单计算逻辑

# 4. 查看该提交的改动
git show abc123

# 5. 结束 bisect
git bisect reset

# 6. 修复 bug
git switch -c fix/order-calculation-bug
# 修复...

跳过特定提交

有时某些提交无法测试(如构建失败):

bash
# 跳过当前提交
git bisect skip

# 跳过某个范围的提交
git bisect skip abc123..def456

bisect 的效率

二分查找的时间复杂度是 O(log n):

提交数量最多需要测试次数
104 次
1007 次
100010 次
1000014 次
10000017 次

相比从最新提交逐个往回检查,效率提升巨大。

总结

操作命令
开始 bisectgit bisect start
标记当前为坏git bisect bad
标记当前为好git bisect good
自动化测试git bisect run <script>
跳过当前提交git bisect skip
查看日志git bisect log
结束 bisectgit bisect reset

git bisect 配合自动化测试,是定位 bug 引入时机的最高效工具,对于大型项目尤其有价值。