Finding a bug when you have no idea where to start

With the help of Git Bisect

TL;DR

  1. Start a session
    git bisect start
    
  2. Set the bad commit

    Either the current commit you're checked out has the bug

    git bisect bad
    

    or a specific commit has the bug, for example, dcf12e8

    git bisect bad dcf12e8
    
  3. Set the good commit (e.g. eff13d3 doesn't have the bug )
    git bisect good eff13d3
    
  4. Run and test the application

    Either the bug is present, then run

    git bisect bad
    

    or the bug is not present, then run

    git bisect good
    
  5. Repeat step 4 until the first bad commit is found

Note: you can use tags instead of commit hashes as well.

When is it useful?

I usually find it quite useful when the two following conditions are met:

  • The bug was not present in the latest release but it's present in the current release candidate
  • I have no idea what is causing the bug (therefore I don't know where to look)

Imagine the following scenario. A new release (let's say 2.80) is about to be released and QA is doing regression. You're enjoying a deserved coffee after a job well done when, unexpectedly, you're tagged on Slack...you know that it's not a good signal...

D'oh!

So, you've just been informed that a blocker was found during regression and it has to be fixed. At this point, several thoughts go through your mind:

"Okay, hopefully, it's not my code that is breaking the app so I'm safe" (AKA throw one of your colleagues under the bus)

"Let's look at the ticket, it will surely be something easy to fix. D'oh! It isn't!"

Okay, you have no choice but to fix it. You read the ticket and the bug is odd. You don't have a clue why it's failing and what is causing it.

The only thing you know for sure is that 2.80 has the bug but 2.79 doesn't. Then, git bisect is your friend in this scenario.

How it works under the hood

Git Bisect relies on the binary search algorithm to find the first bad commit (the commit that introduced the bug). So, let's start by starting the session:

git bisect start

Then, we have to let Git know which commit has the bug for sure and which one doesn't. We know that 2.80 has the bug and that 2.79 doesn't, so:

git bisect bad 2.80 (or git bisect bad if the current commit has the bug)

git bisect good 2.79

At this point, our setup is something like this:

Untitled Diagram.png

Then Git automatically checks out a commit in the middle and we have to run the application to check if the bug is present or not: D'oh!

Let's say that the bug is present in C3 (dcf12e8), then we know that the second half has the bug for sure, therefore, the bug was introduced somewhere in the first half. We have to let Git know that C3 has the bug:

git bisect bad dcf12e8

Now Git automatically checks out a new commit:

Untitled Diagram-Page-2.png

Let's say now that the bug is not present in C1 (eff13d3), then we have to let Git know about this:

git bisect good eff13d3

So the first half is bug-free, therefore, it is discarded. Only the C2 commit is left and Git checks it out, we run the app and let's say that the bug is present. Bingo! The first bad commit has just been found (because C1 is bug-free):

Untitled Diagram-Page-3.png

Finally, Git will provide you with the hash (author, date, etc.) of the first bad commit.

Final thoughts

git bisect is not the Holy Grail, sometimes even if you find the commit that introduced the bug, it's simply not enough to figure out what the problem is.

But, even so, it's a skill that can help you to discard possible scenarios and fence the problem.

Documentation

git-scm.com/docs/git-bisect
git-tower.com/learn/git/faq/git-bisect

Images used

unsplash.com/photos/IClZBVw5W5A

No Comments Yet