git bisect 启动需先执行 git bisect start,再用 git bisect bad 标记当前坏提交、git bisect good 指定已知好提交;Git 自动检出中间节点,用户或脚本验证后标记好坏。

git bisect 怎么启动和标记好坏提交
启动 git bisect 的核心就两步:先告诉 Git 当前是坏的,再指一个已知好的历史点。它不是自动猜,而是靠你人工验证中间节点——所以别指望跳过测试环节。
常见错误是把“好”“坏”标反,或者选了一个其实也不稳定的“好”提交(比如那个提交只是没触发 Bug,但逻辑已有隐患)。结果整个二分过程会收敛到错误位置。
- 用
git bisect start初始化 - 立刻标当前为坏:
git bisect bad(或加具体 commit,如git bisect bad HEAD) - 再标一个确定没问题的旧提交:
git bisect good v1.2.0或git bisect good abc1234 - Git 会自动检出中间 commit,你只需运行测试(手动或脚本),然后执行
git bisect good或git bisect bad
怎么用脚本自动化测试避免手点到崩溃
每次 git bisect 检出新提交后都要跑测试,手动操作 10 轮以上极易出错。用 --run 让 Git 自动调用脚本判断好坏,是提速关键,也是减少人为误判的底线操作。
脚本返回值决定走向:退出码 0 表示“好”,非 0(常用 1)表示“坏”。注意脚本里不能依赖未提交的本地修改,也不能有交互式命令(比如 read 或 vim)。
- 写个简单测试脚本
test.sh,内容类似:#!/bin/sh<br>npm test && python -m pytest tests/test_login.py
- 给它可执行权限:
chmod +x test.sh - 直接运行:
git bisect run ./test.sh - 如果某次测试失败(比如编译不过、Python 报
ImportError),脚本退出非 0,Git 就记该提交为bad
git bisect reset 之后还能找回进度吗
能,但得提前留痕。默认 git bisect reset 会丢掉所有 bisect 状态,包括你已经标记过的 good/bad 提交。很多人以为“反正没 finish,重来就行”,结果发现之前花 20 分钟排除的 5 个提交又得重复验证。
Git 其实把每一步都记在 .git/BISECT_LOG 里,只要没删仓库、没覆盖日志,就能翻出来。但别指望靠它一键恢复——得自己 parse 日志,挑出最后确认的 good 和 bad。
- 查看记录:
cat .git/BISECT_LOG,里面每行是git bisect good/bad <commit> - 最后一行
git bisect bad后面的 commit 很可能就是问题引入点 - 想中途保存状态?用
git bisect log > bisect-backup.txt备份 - 恢复时别直接
git bisect start,先git bisect start <bad> <good>显式指定范围
为什么 git bisect 有时卡在 merge commit 上
因为默认策略下,Git 会把 merge commit 当作一个整体节点参与二分——但它本身不带变更,只是整合两个分支。如果你的 Bug 是某个父提交引入、而 merge 时没暴露,git bisect 可能反复停在这个 merge 上,让你误以为它是根源。
这不是 bug,是设计使然。解决方案是换一种挑选策略,或者跳过 merge commit 主动过滤。
- 用
--no-checkout避免检出,只看日志定位(适合纯代码审查场景) - 加
--first-parent参数:git bisect start --first-parent,这样只沿主干(merge 的第一个 parent)走,忽略 topic 分支带来的干扰 - 如果明确知道 Bug 不在 merge 逻辑里,手动跳过:
git bisect skip,但慎用——跳太多会让搜索空间变模糊 - 注意:某些 CI 环境中
git bisect默认启用--first-parent,本地行为不一致时要核对 Git 版本和配置
真正麻烦的从来不是命令怎么敲,而是你标“good”的那个提交,到底有没有躲过条件竞争、数据边界或异步延迟——这些不会在 git bisect log 里留下痕迹。


















