Finding bugs with git bisect
Has a tester ever pushed your feature back because you've caused a regression, but you're not 100% sure where the bug was introduced? Are you going to checkout each individual commit of a list of potentially hundreds to find the issue? Nah!
Git bisect is a command that performs a search on your commit history, allowing you to pinpoint the exact commit a bug was introduced.
What makes it so powerful is that this search is a binary one, meaning git repeatedly divides in half a set of commits where the bug is known to exist. It continues dividing until you're left with a single commit, the one containing the bug. This makes the process exceptionally efficient. For example, if you know a bug is somewhere in 128 commits since main
, it will only take 7 guesses to figure out which one.
Start the bisect!
To instruct git that you'd like to start bisecting the current repository, use:
$ git bisect start
Check out a commit that you know contains the bug (say the tip of develop
) and instruct git that this commit is a bad one:
$ git bisect bad
Now that we have our bad starting point, tell git which commit is a known good one (say the tip of main
):
$ git bisect good main
These good and bad starting points provide git with a range of commits to search through.
Good, bad, bad, good, good, bad
The next steps are repetitive, but for good reason! After starting the bisect, git will checkout a commit for you to test. The idea here is to perform whatever step is required to determine if the bug is present. This might be compiling the source code, running automated tests, manually testing an app and so on.
If the bug is present, let git know by running:
$ git bisect bad
Git will now search for and checkout another commit to test. If the bug isn't present, let git know:
$ git bisect good
You continue marking each commit as good/bad and at each step you will see output (similar to the following) which lets you know how many steps are left:
$ Bisecting: 31 revisions left to test after this (roughly 5 steps)
When there are no more steps left to perform, git will output details of the offending commit. At this point you are free to examine the changes in more detail.
Finishing up
Once you've handled the bug like a rockstar, use git bisect reset
to finish bisecting and git will return you to your original HEAD
commit.
I'll be honest, I'm surprised (and shocked) that I've not used this previously, but it's definitely now a tool in my toolbox that I'll be using regularly.