Photo by henry perks on Unsplash

Git: finding where the problem relies 🔍

Milan Brankovic
3 min readApr 25, 2020

Almost every developer has been in the situation of finding a bad git commit. The naive approach for doing this would be the following: checkout some old commit, make sure the broken code isn’t there, then checkout a slightly newer commit, check again, and repeat over and over until you find the flawed commit.

But git offers a much better way: git bisect. This command behaves like a little wizard that walks you through range of commits, asks you if they are good or bad, and narrows down to the broken commit. The rationale behind this command is that it pin points the bad commit by divide and conquer. It divides the commit history into two (relatively) equal parts, then determines where the bad commit is by reducing the number of revisions that are potentially bad by half. This process will continue until the bad commit is located.

How does it work?

git bisect uses the binary search to find the first commit that introduced the problem or change that you are looking for. You will have to tell the bisect command one commit for which you are sure that it contains the bug (bad) and one commit for which you know that it does not contain the bug (good). This command divides git history between the good and the bad commit range. It points your current project state to a mid-range commit snapshot. Bisect will then start searching, asking you if a given commit is good or bad, until it has found the commit that introduces the bug. It will pause at each snapshot to allow checking for the bug persistence. If the bug exists, you declare the commit as bad, if not as good unless the search ends.

The process can be broken in three simple steps:

  1. find a commit where things were working
  2. find a commit where things are not working
  3. use git bisect to find the problematic commit

If you have mistakenly declared commit as good or bad there is no possibility to undo this. Bisect needs to be done from the top again (with or without slightly modified range). To do this first run git bisect reset, which will end current bisect session. After that you can start over.

Bisect has the option run, which will run a command/script for you on each iteration. This option can be used for automating the process. If the command succeeds it will mark the commit as good, if the command fails it will mark the commit as bad.

There are two additional useful commands:

  • git bisect visualize : To visualize the currently remaining suspects in gitk, issue the following command during the bisection process. Assuming that gitk is installed and accessible to your path, otherwise it will use git log
  • git bisect log : After having marked revisions as good or bad, this command will show what has been done so far

Practical example

Let's assume that the following picture illustrates git history

Figure 1. git history

and our current version has a problem. The last working commit, which we know from before, is annotated with v1.0 tag. Now we can start looking for the commit with a problem.

$ git bisect start
$ git bisect bad
$ git bisect good e137e9b # or git bisect good v1.0

The output will look something like this:

Bisecting: 5 revisions left to test after this (roughly 2 steps)

We repeat marking commits with good or bad depending of the issue existence.

When the search is done result will look like this:

c0e9f0f is the first bad commit

As the bad commit is identified we can end the search, return to the original HEAD and deal with fixing problem.

$ git bisect reset

git bisect is not used only for searching bug(s), but it can be used to find out when something occurred (e.g. performance improvement/downgrade).

--

--