使用 Git bisect 命令定位首次引入错误的提交
Git
![](/data/attachment/album/202212/02/092549j2o7h9cif3hcu34z.jpg)



> 
> Git 的 bisect 工具通过快速识别坏的提交，节省了时间和精力。
> 
> 
> 


你是不是有过这样的经历：发现代码中有 <ruby> 错误 <rt>  bug </rt></ruby>，但不知道这个错误是什么时候引入的。这有可能是因为，某个人提交了一份有错误的代码，但没有在他的 Git <ruby> 提交 <rt>  commit </rt></ruby> 消息中声明它。这个错误可能已经存在了几周、几个月甚至几年，这意味着你需要搜索数百或数千个提交，才能找到问题何时出现的。而 `git bisect` 命令能够完美地解决这个问题！


`git bisect` 命令是一个强大的工具。你可以给 `git bisect` 命令一个范围，一端是一个已知的好状态，另一端是一个已知的坏状态。它会自动地确认当前范围的中点，在这个中点上进行测试，然后要求你确定那次提交是一个 <ruby> 好提交 <rt>  good commit </rt></ruby> 还是一个 <ruby> 坏提交 <rt>  bad commit </rt></ruby>，然后它会重复这一“二分查找”的过程，直到你找到首次引入错误的那一次提交。


![Image of Zeno's paradox of Achilles.](/data/attachment/album/202212/02/092553nxio349j8ii9aa9f.png)


这个“数学”工具是利用“二分查找”来找到错误之处的。`git bisect` 命令通过**查看中点**，然后由你来决定它是提交列表的新起点（即 “坏提交” ）还是新终点（即 “好提交”），进而来缩小查找范围，如此在几次查找中你可以就能定位到有错误的提交。即使你有 10,000 个提交要检查，最多只需要 13 次查找，就能很快地定位到首次引入错误的提交。


1. 提交 1 坏 <> 提交 10,000 好 => 提交 5,000 是坏的
2. 提交 5,000 坏 <> 提交 10,000 好 => 提交 7,500 是好的
3. 提交 5,000 坏 <> 提交 7,500 好 => 提交 6,250 是好的
4. 提交 5,000 坏 <> 提交 6,250 好 => 提交 5,625 是坏的
5. 提交 5,625 坏 <> 提交 6,250 好 => 提交 5,938 是坏的
6. 提交 5,938 坏 <> 提交 6,250 好 => 提交 6,094 是好的
7. 提交 5,938 坏 <> 提交 6,094 好 => 提交 6,016 是坏的
8. 提交 6,016 坏 <> 提交 6,094 好 => 提交 6,055 是好的
9. 提交 6,016 坏 <> 提交 6,055 好 => 提交 6,036 是坏的
10. 提交 6,036 坏 <> 提交 6,055 好 => 提交 6,046 是坏的
11. 提交 6,046 坏 <> 提交 6,055 好 => 提交 6,050 是坏的
12. 提交 6,050 坏 <> 提交 6,055 好 => 提交 6,053 是好的
13. 提交 6,053 坏 <> 提交 6,055 好 => 提交 6,054 是好的


对于上面这个例子，我们能知道 10,000 个提交中的第一个错误提交是第 6053 次提交。对于 `git bisect` 命令，最多需要几分钟就能完成检索。但是如果要一个一个查找每个提交是否错误，我甚至无法想象需要多长时间。


### 使用 Git bisect 命令


`git bisect` 命令使用起来非常简单：


（LCTT 译注：使用 `git bisect start` 命令来进入 bisect 模式，并且该命令指定了一个检查范围。它会告诉我们一共有多少次提交，大概需要几步就可以定位到具体的提交。）



```
$ git bisect start
$ git bisect bad        # Git assumes you mean HEAD by default
$ git bisect good <ref> # specify a tag or commit ID for <ref>

```

Git 检查中间的提交，并等待你声明这次提交是一个好提交还是一个坏提交：


（LCTT 译注：如果某一提交是可以通过的，则使用 `git bisect good` 命令标记；同样地，如果某一提交不能通过，则使用 `git bisect bad` 命令标记。）



```
$ git bisect good

```

或



```
$ git bisect bad

```

然后，`git bisect` 工具重复检查好提交和坏提交中间的那次提交，直到你告诉它：



```
$ git bisect reset

```

一些高级用户甚至可以自己编写脚本，来确定提交的好坏状态、并在找到特定提交时采取某一补救措施。你可能不会每天都使用 `git bisect` 命令，但当你需要它来定位首次引入错误的提交时，它会是一个很有用的救星。




---


via: <https://opensource.com/article/22/11/git-bisect>


作者：[Dwayne McDaniel](https://opensource.com/users/dwaynemcdaniel) 选题：[lkxed](https://github.com/lkxed) 译者：[chai001125](https://github.com/chai001125) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
Have you ever found a bug in code and needed to know when it was first introduced? Chances are, whoever committed the bug didn't declare it in their Git commit message. In some cases, it might have been present for weeks, months, or even years, meaning you would need to search through hundreds or thousands of commits to find when the problem was introduced. This is the problem that `git bisect`

was built to solve!

The `git bisect`

command is a powerful tool that quickly checks out a commit halfway between a known good state and a known bad state and then asks you to identify the commit as either good or bad. Then it repeats until you find the exact commit where the code in question was first introduced.

![Image of Zeno's paradox of Achilles.](https://opensource.com/sites/default/files/2022-11/beyondgit.paradox.png)

(Martin Grandjean, CC BY-SA 4.0)


This "mathmagical" tool works by leveraging the power of halving. No matter how many steps you need to get through, by looking at the halfway point and deciding if it is the new top or bottom of the list of commits, you can find any desired commit in a handful of steps. Even if you have 10,000 commits to hunt through, it only takes a maximum of 13 steps to find the first offending commit.

- commit 1 bad <> commit 10,000 good => commit 5,000 is bad
- commit 5,000 bad <> commit 10,000 good => commit 7,500 is good
- commit 5,000 bad <> commit 7,500 good => commit 6,250 is good
- commit 5,000 bad <> commit 6,250 good => commit 5,625 is bad
- commit 5,625 bad <> commit 6,250 good => commit 5,938 is bad
- commit 5,938 bad <> commit 6,250 good => commit 6,094 is good
- commit 5,938 bad <> commit 6,094 good => commit 6,016 is bad
- commit 6,016 bad <> commit 6,094 good => commit 6,055 is good
- commit 6,016 bad <> commit 6,055 good => commit 6,036 is bad
- commit 6036 bad <> commit 6055 good => commit 6046 is bad
- commit 6,046 bad <> commit 6,055 good => commit 6,050 is bad
- commit 6,050 bad <> commit 6,055 good => commit 6,053 is good
- commit 6,053 bad <> commit 6,055 good => commit 6,054 is good

So, the first bad commit of the 10,000 is commit number 6,053. With `git bisect`

, this would take a couple of minutes at maximum. I can't even imagine how long this would take to investigate crawling through each commit one at a time.

## Using Git bisect

Using the `git bisect `

command is very straightforward:

```
``````
$ git bisect start
$ git bisect bad # Git assumes you mean HEAD by default
$ git bisect good <ref> # specify a tag or commit ID for <ref>
```


Git checks out the commit in the middle and waits for you to declare either:

```
``````
$ git bisect good
## or
$ git bisect bad
```


Then the bisect tool repeats checking out the commit halfway between good and bad commits until you tell it:

```
````$ git bisect reset`


Advanced users can even write scripts that determine good and bad states as well as any remediation actions to take upon finding the specific commit. You might not use the `git bisect`

command every day of your life, but when you need it, it is a lifesaver.

## 1 Comment