使用 Git Bisect 超级加速调试
Git Bisect 速查表
|
|
陷入困境的调试经历
我在学习 Blazor 时构建了一个简单应用。在功能分支工作一段时间后,我决定测试登出场景。当我尝试重新登录时,登录页面陷入了无限重定向循环。
我尝试了所有能想到的方法:在所有重定向代码处设置断点、允许登录页面匿名访问、调整授权策略,甚至向 Copilot 寻求帮助,但都无济于事。
当我切换回主分支时,发现这个错误也存在!这意味着这个错误已经在代码中存在一段时间了,只是因为我一直保持登录状态而没有注意到。
Git Bisect 救援行动
从文档中可知:
该命令使用二进制搜索算法来查找项目历史中哪个提交引入了错误。你需要先告诉它一个已知包含错误的"坏"提交,以及一个已知在错误引入之前的"好"提交。然后 git bisect 在这两个端点之间选择一个提交,并询问你所选提交是"好"还是"坏"。它会持续缩小范围,直到找到引入更改的确切提交。
关键点是这是二进制搜索。即使你要搜索的提交范围有 128 个提交,最多也只需要 7 步就能找到引入错误的提交(2^7 = 128)。
实际使用示例
|
|
在几次迭代后,git bisect 找到了引入错误的提交:
|
|
问题出现在 App.razor 文件的更改中:
|
|
Git Bisect 的挑战
建议阅读 git bisect 的文档,了解其他重要的子命令。
例如,有时某个提交无法测试(比如构建失败)。在这种情况下,可以调用 git bisect skip 跳过该提交。
在实践中,我发现有时需要对提交进行一些调整才能运行。例如,某个提交出现了构建错误:
|
|
由于我只需要在本地构建和测试,我忽略了该警告以测试该提交。
自动化 Git Bisect
git bisect 有自动化的潜力。你可以编写一个脚本来构建和测试每个提交。如果提交构建或测试失败,脚本可以为你调用 git bisect skip。
例如,可以这样做:
|
|
这将在每个提交上运行 dotnet test,如果测试失败则自动调用 git bisect skip。
然而,在实践中,效果可能不如预期。当你编写时正常的提交可能不再构建。而且,你可能真正想做的是在 git bisect 过程中注入新的测试。
更不用说如果你有访问数据库的集成测试。你必须在 git bisect 过程中运行数据库迁移的上上下下。
读者评论
Max 提到:如果你在使用带有 CI 测试和合并提交的 PR 工作流,可以在主分支上使用 git bisect 的 first-parent 标志,首先确定哪个 PR(合并提交)引入了错误。我发现这个步骤通常可以轻松自动化(因为你的 CI 系统已经强制它们构建)。有时知道是哪个 PR 就足够了。如果你需要深入了解 PR 中的哪个提交,可以分支"第二个父级",并再次受益于 first-parent 标志,仅测试 PR 的"自有"提交,而不是从其他分支带来的任何提交。