Finding bugs with git bisect
This week I deployed a UI change to our development environment only for the app to immediately crash. It wasn't because of my change, but because an unrelated change on main introduced a regression. There were a lot of commits since the last deployment of the app, so I needed a way to narrow down my options in order to fix it.
Enter my favourite git power tool: git-bisect. Bisect helps you find the point in your git history where a change introduced a problem. It essentially guides you through a binary search on your commit history until you can pinpoint the cause.
How to use it
To start using git-bisect, you just run git bisect start:
git bisect start
Next we need to tell git a search range. You can use any ref you like to do this including sha hashes, tags, branches and more. Assuming our current HEAD is bad and the last release (tagged with the git tag v1.2.3) is good, we would then run the following two commands to set up our search radius:
# My current commit is bad:
git bisect bad
# The last release was good. Here we reference it by its tag:
git bisect good v1.2.3
Now git will pick a commit somewhere in the middle of those two. We need to build and test our code, and then tell it if it's still broken:
# Tell git it's still broken:
git bisect bad
# ...or that it's working:
git bisect good
Git will then keep checking out commits until you've narrowed down the offender. When you're all done, run git bisect reset to remove the bisect state from your git repository and go back to what you were doing.
That's it, it's really simple!
Power move: Automating git bisect
It's a bit of a pain to have to keep building and testing your code for every iteration of the search. If your issue can be checked with automated tests, it's worth knocking together a quick script to build and test your code so that git can do all the work for you. The only requirement is that it exits with a non-zero exit code for 'bad' commits (normal for a test suite), and zero for a good commit.
Once you've got your script, you can tell git to get on with figuring out the problem using the git bisect run command:
# We still need to tell git bisect what good and bad look like first:
git bisect start
git bisect bad
git bisect good v1.2.3
# Assuming my build and test script is at 'reproduce.sh'
git bisect run ./reproduce.sh
Now just go and make a coffee, and wait till your computer tells you where your problems lie!
There are lots of details to read up on in the documentation.