发布于 2026-01-06 2 阅读
0

Git Bisect——调试变得轻松简单

Git Bisect——调试变得轻松简单

从前,有个年轻的开发者在做一个小项目。几个小时后,他做出了一个可运行的版本,然后开始重构代码,让它更简洁、更清晰。他花了几个小时重构代码,每次提交的都是小而有意义的代码。当他对自己的工作感到满意时,他再次运行代码,结果却发生了可怕的事情……代码无法运行了。

我们都经历过这种情况,对我来说,就在一周前,我坐在床上盯着我的IDE,它告诉我,那段有bug的代码是我自己写的。“我肯定只能怪自己了。”我暗自得意,但片刻之后,一个新想法突然闪现——💡如果我可以用Git遍历我所有的提交,找出bug呢?幸运的是,在谷歌上简单搜索了一下之后,我发现这是可以实现的——使用简单的git bisect命令。

在本教程中,我们将探索该git bisect命令。我们将讲解它的工作原理、用途以及使用方法,希望您也能像我一样发现它实用且强大!

🔮使用 Git 进行调试

正如你可能知道的,对于 Git 来说,一切都围绕着提交展开,分支实际上只是指向单个提交的指针。这使得 Git 能够遍历提交,并提供一些调试工具来帮助我们调试代码:文件注释(也称为“git blame”)和二分查找。

如果您想了解更多关于 git 底层工作原理和数据存储方式的信息,请查看我最近的文章git 文档以获取更多阅读材料。

文件注释 — git blame

文件注解会显示最后一次修改任何文件每一行的提交记录,这是通过git blame命令完成的。这通常是追踪 bug 并找出责任人的最有用工具。如果您不熟悉 Git 的文件注解,我强烈建议您阅读 Git 官方文档

二分查找 — git bisect

这种方法可以通过在特定分支的所有提交历史记录中使用二分查找来定位引入问题的提交。它使用一个git bisect命令来检出每个提交,从而允许你运行测试来查看问题是否存在于该提交中。当你在查找 bug 时,如果你不知道从哪里入手,而且自你记得的最后一个正常提交以来已经有数百个提交,那么这个git bisect命令就是你的答案。

📽 简单场景

假设你负责一个新分支……

🥳 你努力了一段时间,终于取得了不错的成绩,做出了一个运行良好的产品。

😌 您也是一位负责任的开发者,希望保持代码树的整洁,因此您可能在此过程中添加了一些提交,并拥有以下提交历史记录:

*-----*--*---271cb1c (current)

💎 你决定是时候开始重构代码了,让它更简洁美观,最终得到了以下提交历史:

*-----*--*---271cb1c-*-66e0075-*-...--*---9c07a95 (current)

😰 很遗憾,你的代码在当前的提交版本中无法正常工作,显然在某个地方代码出现了问题。

🧐 你知道在重构之前(也就是你添加提交的时候)它肯定是有效的,这意味着在提交271cb1c之间代码中存在一个错误,唯一的问题是……你如何找到它?271cb1c9c07a95

👑 进入git bisect

🛠 如何使用它

受克林特·伊斯特伍德的启发,我喜欢把这部分看作是“好人、坏人和巫师”的故事:

🧙🏼‍♂️ 巫师

运行git bisect start命令启动向导git bisect

😈 坏的

二分查找的工作原理git是反复将可能包含 bug 的提交记录一分为二,从而将范围缩小到单个提交记录。因此,搜索范围的设定至关重要。要定义git bisect搜索范围,需要运行一个git bisect bad命令,该命令会指示git某个current提交记录存在问题,并且包含一个传染性 bug。

😇 好的

错误的提交只是问题范围的一端,现在我们需要确定git最后一个已知的正确提交是什么时候。我们可以通过运行 git bisect<good_commit>命令来实现这一点。例如,在我们的例子中,正确的提交是 commit 1,271cb1c所以我们将运行以下命令:

git bisect 271cb1c

运行此命令后,程序git将使用二分查找法检出提交,并允许程序在每次提交时构建应用程序并检查是否存在错误。您只需确保使用 `--status` 或 `--status` 命令告知程序上一个命令git的状态,以便程序继续缩小可能的提交范围。重复此过程,直到找到引入错误的提交。 假设我们检出了某个提交,并且发现错误发生在该提交之前,因此我们运行:git bisectgit bisect badgit bisect good
66e0075

git bisect bad

🙌🏻 Git真好

现在git它拥有了所有必要的信息,可以确定在提交 A66e0075和提交 B之间271cb1cis哪个提交引入了错误。当git最终找到包含错误的提交时,它会打印出所有相关信息,以帮助您找出可能导致此错误的原因,例如:

$ git bisect bad
66e00756e887030abcbde19ac3e10a7c2942036a is the first bad commit
commit 66e00756e887030abcbde19ac3e10a7c2942036a
Author: Noaa Barki <noaa@datree.io>
Date:   Sun Apr 26 12:10:56 2020 +0300
fix: added client
base/client.go                              
base/client_test.go                          
1 files changed, ......
 create mode 100644 base/client_test.go

🧙🏼‍♂️巫师

就像所有时间旅行一样,回到一切开始的地方至关重要,否则我们可能会停留在过去的某个提交状态,最终陷入一个奇怪的分支状态。我们通过运行一个简单的git bisect reset命令回到现在,该命令会关闭git bisect向导并将状态重置HEAD到开始之前。

🤖 自动化

这部分才是git bisect真正精彩之处——其中一个子git bisect命令git bisect run接受一个命令作为参数,并允许完全自动化git bisect

git bisect run <cmd>...

运行此命令后,git系统会自动cmd对每个检出的提交运行该命令,并使用该调用的返回值来判断提交是好是坏,直到找到第一个损坏的提交为止。

如何使用它

首先,你需要git提供错误提交和正确提交,来确定二分查找的范围:

$ git bisect start <bad_commit> <good_commit>

然后你git bisect run只需发出指令,让它git为你完成所有工作,例如:

$ git bisect start HEAD 991debbc8b9e05ddc217023a898109822a70dd60
$ git bisect run npm run test

该命令可以是任何脚本,该脚本对于“提交成功”将返回 0,对于“提交失败”将返回非 0。

🌸 总结

在本教程中,您学习了如何使用命令来追踪错误git bisect。此外,您还学习了如何实现自动化,从而显著缩短调试时间。希望您将来git bisect在寻找有效的错误追踪解决方案时能够尝试一下。

特别感谢我在datreeio的队友们🙏🏻

文章来源:https://dev.to/noaabarki/git-bisect-and-debugging-is-easy-4706