让 Git Bisect 帮助你

Git 提供来很多的工具来帮助我们改进工作流程。 bisect 命令就是其中之一, 虽然由于使用得不多而不广为人知,但是当你想知道一个本来好的分支从什么时候开始变坏时,它就能派上用场了。到底是哪一次提交把事情搞砸了呢,让 bisect 来告诉你吧。

Bisect 基于二分查找算法。给定一个有序的元素序列,它会返回要你要查找的元素的序号(或者告诉你该元素是否在序列中)。它基于如下的不变式:当你对比完一个元素,你就能根据比较的结果抛弃掉它之前或者之后的所有元素(从而大大缩小下次查找的范围)。

如果你有去过图书馆,那你可能注意到了每个专区内的书籍都是按作者姓名来排序的。比方说你要找的一本书的作者的姓为 Martin,而你刚刚看到某个书架上的最后一本书的作者的姓是 F 开头的,那么你就能确定你要找的书一定放在后面的某个书架上。依此方法继续下次,你就能快速的缩小搜索范围直到找到你要的书为止。

二分查找法亦是如此。如果你想在有 n 个元素的序列(有序的)中查找元素 x,你挑出第 n/2 个元素并将其与元素 x 比较。如果 x 大,那么就对从 n/2+1 到 n 的子序列重复上述步骤,反之,就对从 1 到 n/2-1 的子序列重复上述步骤, 这样一直递归下去。这里就有一个 关于此算法的有趣的演示。

二分查找算法所需的比较次数通常都比你傻傻的去拿序列中的每个元素与 x 比较所需的比较次数少得多。事实证明在有序序列中查找元素,二分查找更快更有用。

Bisect

Bisect 就是利用二分查找发来查找在你的某一分支中到底是哪一次提交引入了特定的变更。

首先,也是最起码的,你得有办法检测出一个给定的提交点是不是有 bug。通常你可以写个测试代码,如果这也不可能的话,那至少你得有一套步骤来使 bug 再现出来。

有了这套检测方法,你就可以开始用 bisect 查找你的提交历史来以最快的速度发现引入 bug 的时间点了。等等,你还得准备好两个提交点:一个是你确定 bug 还没有被引入的提交点,另一个则是确定 bug 已经引入了的提交点(这样就缩小了初始的查找范围)。在 bisect 命令上,你可以用哈希值(hash)或者标签(tag)来引用这两个提交点。bisect 查找时,查找范围里的提交点要么被标记为好的(通过测试,没有 bug 的),要么被标记为坏的(通不过测试,有 bug 的)。

让 Git Bisect 帮助你

上图演示了 bisect 的执行步骤(绿点是好的提交点,红点的就是坏的):bisect 被要求在提交点 1 到 8 这个范围内查找首次引入 bug 的提交点(看图一目了然是提交点 6),这里提交点 1 和 8 就是上段中提及的,我们需要首先准备好给 bisect 命令的两个(一好一坏)提交点。bisect 首先用调用者提供的检测方法来测试 1 到 8 中间的提交点 4,如果它是好的(图上的情况),那么 bisect 就缩小范围为它右边的区域,重复上述步骤,反之,则选择其左边的区域为新的搜索范围。如此递归下去,在上图的例子中,只需要 3 步就确定了罪魁祸首是提交点 6.

我这里创建了一个 git 仓库,里面共有 1024 个提交记录,每个提交都往一个文本文件后面添加一个递增的数字,从 1 到 1024,一行一个数字。我们的任务是要找出是哪个提交点向文本文件附加了 1013 这个数字(我们假定它就是一个 bug)。

首先,我们定出一个方法来判断文件里面有没有这个数字。这就是一个测试了。方法很简单:

$ grep 1013 file.txt

有了这条命令,我们就可以开始 bisect 了:

$ git bisect start

对 master 分支(的头部提交点)运行这个测试,没有得到想要的结果(就是没有任何输出),所以我们把它标记为坏的。

$ git bisect bad

现在让我们指定一个好的提交点:假设第一个提交点(7c0dcfa)是没有 bug 的。我们可以检出(check out)这个提交点并标记它为好的提交点(git bisect good + 该提交点的哈希值)。

$ git bisect good 7c0dcfa
Bisecting: 511 revisions left to test after this (roughly 9 steps)
[8950f7db7e7cad0b2dc394ff9b75fc3d38c9d72a] added 512

也可以用下面的命令,完成上面的所有步骤:

$ git bisect start master 7c0dcfa

git bisect start 命令可以接受两个参数,第一个是坏的提交点,第二是好的提交点。

很好,git bisect 自动检出了正中间的提交点,运行我们的检测命令,没有任何的输出(没有 bug),因此我们把该提交点标记为好的。

$ grep 1013 file.txt
 
$ git bisect good
Bisecting: 剩余 255 个修订待测试 (大概还需要 8 步)
[a01ba83f3500b48da97c5f5c33052623aaa4161a] added 768

$ grep 1013 file.txt
 
$ git bisect good
Bisecting: 剩余 255 个修订待测试 (大概还需要 8 步)
[a01ba83f3500b48da97c5f5c33052623aaa4161a] added 768

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/17180.html