如何使用git bisect?

我读过一些文章说, git bisect真棒,但我不是母语,我不明白为什么它真棒。

你可以请示例代码示例什么是如此惊人的呢? 这是否像svn blame

git bisect背后的想法是在历史中执行二分search以find特定的回归。 想象一下,你有以下的发展历史:

 ... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current 

你知道你的程序在current修订版本中工作不正常,并且正在修订版本0 。 所以这个回归可能是在当前提交的1中的一个中引入的。

您可以尝试检查每个提交,构build它,检查回归是否存在。 如果有大量的提交,这可能需要很长时间。 这是一个线性search。 我们可以做一个二进制search做得更好。 这是git bisect命令的作用。 在每一步,它都会尝试减less可能坏一半的版本的数量。

你会使用这样的命令:

 $ git stash save $ git bisect start $ git bisect bad $ git bisect good 0 Bisecting: 2 revisions left to test after this (roughly 2 steps) [< ... sha ... >] 3 

在这个命令之后, git会检出一个提交。 在我们的例子中,这将是提交3 。 你需要build立你的程序,并检查回归是否存在。 你还需要告诉git这个修订版本的状态,如果回归是存在的,那么git bisect bad ,或者如果git bisect good没有关联, git bisect good

假设回归是在提交4中引入的。 然后在这个版本中不存在回归,我们把它告诉git

 $ make $ make test ... ... ... $ git bisect good Bisecting: 0 revisions left to test after this (roughly 1 step) [< ... sha ... >] 5 

然后它将检出另一个提交。 45 (因为只有两个提交)。 我们假设它select了5 。 build立之后,我们testing程序,看看回归是否存在。 然后我们把它告诉git

 $ make $ make test ... ... ... $ git bisect bad Bisecting: 0 revisions left to test after this (roughly 0 steps) [< ... sha ... >] 4 

我们testing最后的修订, 4 。 而且由于它是引入了回归的那个,我们把它告诉git

 $ make $ make test ... ... ... $ git bisect bad < ... sha ... > is the first bad commit < ... commit message ... > 

在这种简单的情况下,我们只需要testing3个版本( 3 )而不是4( 4 )。 这是一个小小的胜利,但这是因为我们的历史是如此之小。 如果search范围是N提交,我们应该期望testing1 + log2 N提交与git bisect而不是大致N / 2提交与线性search。

一旦你find了引入回归的提交,你可以研究它来find问题。 一旦完成,你可以使用git bisect reset来在使用git bisect命令之前把所有的东西都恢复到原来的状态。

如果你有一个自动化的testing脚本 ,退出状态0,如果testing正常,你可以自动find对bisect run的错误:

 git bisect start # Tell Git that the current commit is bad. git bisect bad git checkout HEAD~9 ./test # If the above test passed, tell Git that the current commit is good. # Immediately check out to `bad~5`, the middle commit. git bisect good # Automatically check out to the first failing rev. git bisect run ./test # Check out to master and end the bisect operation. git bisect reset 

其他有用的操作

留在对分之后的第一个失败的提交,而不是回到master

 git bisect reset HEAD 

start +初始badgood

 git bisect start HEAD HEAD~10 

是相同的:

 git bisect start git bisect bad git bisect good HEAD~9 

看看到目前为止已经testing过的东西(通过手动的badrun ):

 git bisect log 

示例输出:

 git bisect log git bisect start # bad: [00b9fcdbe7e7d2579f212b51342f4d605e53253d] 9 git bisect bad 00b9fcdbe7e7d2579f212b51342f4d605e53253d # good: [db7ec3d602db2d994fe981c0da55b7b85ca62566] 0 git bisect good db7ec3d602db2d994fe981c0da55b7b85ca62566 # good: [2461cd8ce8d3d1367ddb036c8f715c7b896397a5] 4 git bisect good 2461cd8ce8d3d1367ddb036c8f715c7b896397a5 # good: [8fbab5a3b44fd469a2da3830dac5c4c1358a87a0] 6 git bisect good 8fbab5a3b44fd469a2da3830dac5c4c1358a87a0 # bad: [dd2c05e71c246f9bcbd2fbe81deabf826c54be23] 8 git bisect bad dd2c05e71c246f9bcbd2fbe81deabf826c54be23 # bad: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05] 7 git bisect bad c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05 # first bad commit: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c0 

考虑这个testing回购,如果你想玩弄命令。

TL; DR

开始:

 $ git bisect start $ git bisect bad $ git bisect good <goodcommit> 

Bisecting: X revisions left to test after this (roughly Y steps)

重复:

问题依然存在?

  • 是的: $ git bisect bad
  • 不: $ git bisect good

结果:

 <abcdef> is the first bad commit 

完成时:

 git bisect reset 

只是补充一点:

我们可以指定一个文件名或path来git bisect start ,以防我们知道这个bug来自特定的文件。 例如,假设我们知道引起回归的变化在com / workingDir目录下,那么我们可以运行git bisect start com/workingDir这意味着只有改变了这个目录内容的提交会被检查,这样做事情更快。

另外,如果很难判断一个特定的提交是好还是坏,你可以运行git bisect skip ,这会忽略它。 鉴于有足够的其他提交,git bisect将使用另一个缩小search范围。

$ git bisect ..基本上是一个用于debuggingGit工具 。 'Git Bisect'通过完成上次(已知)工作提交之前的提交进行debugging。 它使用二进制search来通过所有这些提交,以达到引入回归/错误的那个。

$ git bisect start #开始对分

$ git bisect bad #说明当前提交(v1.5)具有回归/设置“不好”的一点

$ git bisect good v1.0 #提到它最后一个良好的工作提交(没有回归)

这个提到'坏'和'好'点将帮助git bisect (二进制search)select中间元素(提交v1.3)。 如果回退是在v1.3提交的,你会把它设置为新的“坏”点,即( 好 – > v1.0和坏 – > v1.3

 $ git bisect bad 

或者类似的,如果提交v1.3是无bug的,你会把它设置为新的“好点”即(*好 – > v1.3和坏 – > v1.6)。

 $ git bisect good