Follow twitter

How to use git bisect to find the commit that introduced a bug

Have you ever encountered a situation where a feature that used to work fine in your project suddenly stopped working? You might wonder which commit caused the problem and how to fix it. This is where git bisect comes in handy.

Git bisect is a command that helps you find the commit that introduced a bug or changed a property of your project using a binary search algorithm. You need to specify at least one good commit and one bad commit, and then git bisect will check out a commit in between and ask you to test it. You can then mark the commit as good or bad depending on the test result. This process will narrow down the range of commits until you find the first bad commit.

In this blog post, I will show you how to use git bisect to find the commit that broke a feature in your project.

Basic bisect commands: start, bad, good

Let’s say you want to find the commit that broke a feature that was working fine in version v2.6.13-rc2 of your project. You can start a bisect session like this:

$ git bisect start
$ git bisect bad # Current version is bad
$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 is known to be good

Git bisect will then choose a commit between the two endpoints, check it out, and output something like this:

Bisecting: 675 revisions left to test after this (roughly 10 steps)

You need to compile and test the checked out version. If the version works correctly, you type:

$ git bisect good

If the version does not work, you type:

$ git bisect bad

Git bisect will then respond with something like this:

Bisecting: 337 revisions left to test after this (roughly 9 steps)

You repeat this process: compile, test, and run git bisect good or git bisect bad depending on the test result, until there are no more revisions to inspect. The command will then output the description of the first bad commit. The refs/bisect/bad will point to that commit.

Bisect reset

After a bisect session, you can clean up the bisect state and return to the original head by running this command:

$ git bisect reset

By default, this will bring your tree back to the commit that was checked out before git bisect was started (a new git bisect start will also clean up any old bisection state, so you can start it without running this command). You can use an optional argument to go back to another commit instead.

$ git bisect reset <commit>

For example, git bisect reset bisect/bad will check out the first bad revision, while git bisect reset HEAD will leave you at the current bisection commit without switching commits at all.

Alternative terms

You might want to find the commit that changed a property of your project instead of a commit that broke something. For example, you might want to find the commit that fixed a bug or improved the performance of a benchmark. In such cases, using the terms “good” and “bad” to indicate “before change” and “after change” might be very confusing. Therefore, you can choose to use the terms “old” and “new” instead of “good” and “bad” (note that you cannot mix “good” and “bad” with “old” and “new” in one session).

In this more general usage, you give git bisect some new commits that have some property and some old commits that do not have that property. Every time git bisect checks out a commit, you test whether that commit has the property or not. If it does, you mark the commit as “new”. Otherwise, you mark it as “old”. When the bisection is done, git bisect will report which commit introduced the property.

To use “old” and “new” instead of “good” and “bad”, you need to run git bisect start without any commit arguments and then add commits with the following commands:

git bisect old [<rev>]

This marks a commit as before the change, while

git bisect new [<rev>]

marks a commit as after the change.

You can also use your own terms instead of “good” or “bad”, or “new” or “old” by using the --term-{old,good} and --term-{new,bad} options of git bisect start. The old (new) term can be retrieved with git bisect terms --term-old or git bisect terms --term-good.

Summary

Git bisect is a useful tool to find the commit that introduced a bug or changed a property of your project. You can use it with different terms to suit your needs. You can also automate the testing process with a script or run other commands like git bisect log or git bisect visualize to inspect the bisection process. I hope this blog post helped you understand how to use git bisect and make your debugging easier.

Have a nice Git life!