Finding the Cause of a Bug with Git Bisect

Written by: on July 29, 2016

So you have discovered a bug in your project. You might ask, “How long has it been this way,” and “What caused it?” If you are unfamiliar with the project’s source code you may also be wondering where to start.

We would like to identify the root cause of a bug to understand why it was introduced so that we are confident we are making an appropriate fix. Otherwise we might be treating a symptom which may result in consequential bugs that leaves our codebase in a poorer state. Git’s bisect command can be a fantastic tool for identifying the root cause of a bug.

Bisect enables you to perform a binary search on your commit history. After specifying bounds on your commits, bisect will procedurally select commits for you to test until you have isolated the commit that introduced the bug. From here, you should now have a pretty good idea of what the problem is depending on how informative your commit messages are and how much code changed in each commit. It behooves us to think carefully about how we craft our commits for the sake of our future selves.

To get started, signal that you are starting the search with git bisect start to enter bisect mode. Specify the reference to both a known good commit and bad commit using bisect good <ref> and bisect bad <ref> . When done, bisect automatically checks out a commit for you to test. Tell bisect whether this commit is good or bad and it will check out the next commit for you. If you come across a commit that you cannot test, such as an intermediary commit for a feature that was incomplete, use bisect skip to move on to an adjacent commit.

When done, you will get a commit reference for what caused this bug.

Use bisect reset to exit bisect mode and return to the commit you were on before starting the bisect. There are also some other useful commands such as bisect terms and bisect log. See the more documentation for bisect.

Because you are performing a binary search between given upper and lower bounds of your history, you have already reduced the number of tests to do. Nevertheless, bisecting can be a time-consuming process, so there is a cost-time tradeoff to consider before performing a search. Depending on the bug, you can automate this process using bisect run <script> <arguments>. In addition, you may find that old commits are no longer testable for any variety of reasons, such as a change in compilation tool versions, and patching old commits may not be a viable option.

Bisect is little more than a command line tool that performs a binary search on your git history to narrow in on the cause of a bug. If history is rich, you may find that bisect identifies the root cause without having to sift through much source code. Conversely, if history is lengthy, you may find this process tedious without automation which may not always be feasible. The next time you are confronted with a mystifying bug, give bisect a chance and become more confident that you have identified the root cause of a bug.

Christopher Hale

Christopher Hale

Christopher is a multidisciplinary software engineer and a bouldering enthusiast. You can follow him on Twitter.

Add your voice to the discussion: