git-bisect-forensics

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Git Bisect & Forensics

Git Bisect与代码溯源分析

Bisect: Binary Search

Bisect:二分查找

bash
git bisect start <bad> <good>     # or: start; bad; good <tag>
bash
git bisect start <bad> <good>     # 或者:依次执行start; bad; good <标签>

git checks out midpoint; you test, then:

Git会检出中间提交;你进行测试后,执行:

git bisect good | bad | skip git bisect reset # finish, back to original HEAD
undefined
git bisect good | bad | skip git bisect reset # 结束操作,回到原HEAD
undefined

Automated

自动化执行

Exit codes:
0
good,
1–124,126,127
bad,
125
skip,
≥128
abort.
bash
git bisect start HEAD v1.4.0
git bisect run ./reproduce.sh
git bisect run sh -c 'cargo build && cargo test --test regression'
1000 commits → ~10 test runs.
退出码:
0
表示正常,
1–124,126,127
表示异常,
125
表示跳过,
≥128
表示终止。
bash
git bisect start HEAD v1.4.0
git bisect run ./reproduce.sh
git bisect run sh -c 'cargo build && cargo test --test regression'
1000个提交只需约10次测试。

Save / Resume

保存/恢复

bash
git bisect log > bisect.log
git bisect reset
bash
git bisect log > bisect.log
git bisect reset

later:

后续恢复时:

git bisect replay bisect.log
undefined
git bisect replay bisect.log
undefined

Blame

Blame

bash
git blame -L 40,80 file.py                 # line range
git blame -L :funcName:file.py             # by function
git blame -w file.py                       # ignore whitespace-only
git blame -C file.py                       # detect moves within same-commit diffs
git blame -C -C -C file.py                 # across files in any commit (thorough)
git blame --ignore-rev <sha> file.py       # skip a mass-format commit
git config blame.ignoreRevsFile .git-blame-ignore-revs
-C
bypasses "moved file → blame points at the move commit."
bash
git blame -L 40,80 file.py                 # 指定行范围
git blame -L :funcName:file.py             # 按函数指定
git blame -w file.py                       # 忽略仅空白字符的变更
git blame -C file.py                       # 检测同一提交内的代码移动
git blame -C -C -C file.py                 # 跨文件检测任意提交中的代码移动(全面检测)
git blame --ignore-rev <sha> file.py       # 跳过批量格式化的提交
git config blame.ignoreRevsFile .git-blame-ignore-revs
-C
参数可以避免“文件被移动后,blame指向移动提交”的问题。

Pickaxe

Pickaxe搜索

bash
git log -S"token"                  # when token count in file changed
git log -S"pat" --pickaxe-regex
git log -G"regex"                  # any line matching was touched
git log -L :ClassName:src/p.ts     # full evolution of a symbol
git log --follow -p -- path        # history across renames
  • -S
    : added/removed detection (precise).
  • -G
    : any touch of matching lines (broader).
bash
git log -S"token"                  # 追踪文件中该标记出现次数的变更
git log -S"pat" --pickaxe-regex
git log -G"regex"                  # 追踪匹配正则表达式的行的任意变更
git log -L :ClassName:src/p.ts     # 追踪某个符号的完整演变历史
git log --follow -p -- path        # 追踪文件重命名后的历史
  • -S
    :检测标记的添加/移除(精确匹配)。
  • -G
    :检测匹配行的任意修改(范围更广)。

Combo: Narrow then Bisect

组合用法:先缩小范围再Bisect

bash
git log -S"oldLogic" -- src/       # last clean commit
git bisect start HEAD <that-sha>
git bisect run pytest tests/test_regression.py
bash
git log -S"oldLogic" -- src/       # 找到最后一个正常的提交
git bisect start HEAD <that-sha>
git bisect run pytest tests/test_regression.py

Pitfalls

注意事项

  • On commits that don't build, return 125 (skip), not 1, from the bisect script.
  • -S
    is literal by default; use
    --pickaxe-regex
    .
  • Bisect leaves detached HEAD — always
    git bisect reset
    before committing.
  • 对于无法构建的提交,bisect脚本应返回125(跳过),而非1。
  • -S
    默认是字面匹配;如需正则匹配请使用
    --pickaxe-regex
  • Bisect操作会使HEAD处于分离状态——提交前务必执行
    git bisect reset