跳转到内容

Git 调试:Blame 与 Bisect

在软件开发中,Bug 是无法避免的。当生产环境出现问题,或者你发现一段代码逻辑奇怪时,Git 提供了两个强大的工具来帮助你回答两个关键问题:“这是谁写的?”(git blame)以及“这个 Bug 是什么时候引入的?”(git bisect)。

git blame 是一个“甩锅”工具(开玩笑),它的主要用途是注释文件的每一行,显示最后修改该行的提交哈希、作者和时间。这对于理解代码背后的上下文非常有帮助。

查看某个文件的逐行修改历史:

Terminal window
git blame src/utils/calculator.ts

输出示例:

Terminal window
5a3d12f9 (Alice 2023-10-01 14:30:00 +0800 1) export function add(a, b) {
5a3d12f9 (Alice 2023-10-01 14:30:00 +0800 2) return a + b;
7b8c92a1 (Bob 2023-11-15 09:15:00 +0800 3) }
  • 指定行范围 (-L):文件很大时,只查看特定函数或行范围。
    Terminal window
    # 查看第 10 到 20 行
    git blame -L 10,20 src/app.tsx
  • 忽略空白修改 (-w):如果某行代码只是缩进改变了,你可能更关心实际逻辑的修改者。
    Terminal window
    git blame -w src/app.tsx
  • 显示邮箱 (-e):显示作者邮箱而不是名字。

当你发现一个 Bug,但不确定它是哪次提交引入的,且提交历史很长时,手动一个一个 checkout 去验证效率极低。git bisect 利用二分查找算法(Binary Search),能以 $O(\log N)$ 的时间复杂度迅速定位“罪魁祸首”。

假设当前版本(HEAD)是坏的(存在 Bug),而你记得两周前的 v1.0.0 是好的。

  1. 启动二分查找

    Terminal window
    git bisect start
  2. 标记坏点(当前)

    Terminal window
    git bisect bad
    # 或者 git bisect bad HEAD
  3. 标记好点(已知无 Bug 的版本)

    Terminal window
    git bisect good v1.0.0
    # 或者某个具体的 commit hash

    此时,Git 会自动计算中间的提交,并 checkout 到该状态:

    Terminal window
    Bisecting: 100 revisions left to test after this (roughly 7 steps)
    [3a1b2c...] refactor: update user login logic
  4. 验证与反馈: 现在你需要运行项目或测试用例,检查 Bug 是否存在。

    • 如果 Bug 存在,告诉 Git:
      Terminal window
      git bisect bad
    • 如果 Bug 不存在,告诉 Git:
      Terminal window
      git bisect good

    Git 会根据你的反馈,再次切分剩余的一半历史,重复此过程,直到定位到引入 Bug 的那次具体提交。

  5. 结束查找: 找到问题提交后,Git 会输出类似信息:

    Terminal window
    8d9e1f... is the first bad commit
    commit 8d9e1f...
    Author: Charlie <charlie@example.com>
    Date: Tue Dec 12 10:00:00 2023 +0800
    feat: optimize loop performance

    任务完成后,切回原来的工作分支:

    Terminal window
    git bisect reset

如果你有一个脚本或测试命令可以自动判断 Bug 是否存在,你可以让 bisect 自动运行。

退出码规则

退出码含义说明
0Good当前版本正常,不存在 Bug
1-124, 126-127Bad当前版本存在 Bug
125Skip当前版本无法测试(如编译失败),跳过
Terminal window
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
# 开始自动运行
# 语法:git bisect run <cmd>
git bisect run npm test

Git 会自动在每个检查点运行 npm test,根据退出码自动标记 good/bad,喝杯咖啡回来就能看到结果了。

  • 使用 git blame 快速查看代码行的最后修改者,结合 -w 忽略格式变更。
  • 使用 git bisect 在庞大的提交历史中像手术刀一样精准定位 Bug 引入点。学会自动化 bisect run 可以极大地节省调试时间。