Please wait...
git, debugging

Debugging with git bisect

We all use version control software to help keep track of changes to our software projects.  Well, we all should use version control software to help keep track of changes.  If you're not using versioning control on all of your software projects, then you shouldn't be reading this.  You've most likely got loads to do to sort out conflicts, bugs, disappearing code, etc.  So you should stop reading this and get to work cleaning up your codebase!

Still here? Great! If you're reading this, you're likely using git as your VCS. If you're like lots of developers though, you've probably memorized a few commands: git clone, git fetch, git pull, git push. Maybe you're a bit more savvy and you've even managed to memorize git remote add, git remote -v, etc. Maybe you didn’t know that git is very helpful for tracking down hard-to-find bugs. Using git bisect, you can track down even the most hard-to-find bugs quickly and easily. Let’s take a look.

In this post, I’ll simulate work being done on a project by writing and then adding to a small php script, adding and committing it to git at each iteration. At some point in the process, a bug will be introduced into the code, but I’ll simulate that bug making it past the testing phase by adding and committing more changes after the bug is introduced.

Feel free to follow along in your terminal application.

Create a directory (call it git-bisect, or whatever you like), and cd into it.

mkdir git-bisect

cd git-bisect

Initialize your git repo:

git init

Now create a small script to simulate an actual project. This is script.php:

Now, add and commit this script:

git add -A

git commit -m”Added script.php”

Now make a few changes:

Again, add and commit:

git add -A

git commit -m"Made other_strings variable an array"

Now make some more changes:

git add -A

git commit -m"Printing the contents of other_strings array"

Another change:

git add -A

git commit -m"Added conditional testing to printing loop”

Now, this change of course causes a bug by setting our string in the conditional check instead of checking for equality. The old ‘=“ instead of ‘==‘. We’ve all been there…. But let’s say for the sake of example that this wasn’t caught during testing, and work continues in the same file:

git add -A

git commit -m"Print the STRING constant.”

Then one last change is made:

git add -A

git commit -m"Added conditional check for STRING constant.”

Now for the sake of argument, let’s say the bug is discovered here. We know that the change we made to check the value of the STRING constant couldn’t have caused this bug, so it must be something that was not caught in an earlier commit. Let’s use git bisect to find it.

git log shows this:

Now, we know that things were working well when we added the script.php file. (SHA: 4dd09204797b8122521e12c638d467c8a34f080b), and we know that things are broken in the most recent commit (SHA: e82c9ae4aca074a06c5f4eaeb58a7fe1563e856c).

git bisect start

git bisect good 4dd09204797b8122521e12c638d467c8a34f080b

git bisect bad e82c9ae4aca074a06c5f4eaeb58a7fe1563e856c

Bisecting: 2 revisions left to test after this (roughly 1 step)

[0075e8900029f4fcf77b5ef8b9dd6757d55ac43d] Printing the contents of other_strings array

Now check to see if the bug is still occurring:

php script.php

Git bisect helps us track down hard-to-find bugs!

Git bisect is easy to use.

Git bisect rocks.

No bug here, so issue the following command:

git bisect good

Bisecting: 0 revisions left to test after this (roughly 1 step)
[4ac051da4380df5a34ee06d94f0753803da81e06] Print the STRING constant.

Check again to see if the bug is present:

php script.php

Git bisect helps us track down hard-to-find bugs!

============ This rocks. =============

Git bisect is easy to use.

============ This rocks. =============

Git bisect rocks.

============ This rocks. =============

Hello, bisect

It is, so issue:

git bisect bad

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

[67bc4c8026c2b2875997ca6b4dcd56cd56882d6c] Added conditional testing to printing loop

Check for the bug again:

php script.php

Git bisect helps us track down hard-to-find bugs!

============ This rocks. =============

Git bisect is easy to use.

============ This rocks. =============

Git bisect rocks.

============ This rocks. =============

Hello, bisect

The bug is present, so:

git bisect bad

67bc4c8026c2b2875997ca6b4dcd56cd56882d6c is the first bad commit

commit 67bc4c8026c2b2875997ca6b4dcd56cd56882d6c

Author: axlroach

Date: Wed Sep 26 11:23:29 2018 +0100

Added conditional testing to printing loop

:100644 100644 91fa5ae115fb78db7a2cdca07fc13b2e829c93b8 b753c18f03d50c293b1159ca5a854045503ed1e6 M script.php

Look at that! git bisect has shown us the first bad commit! Fantastic! Now we can use the following statement to see exactly what changed in this commit so that we can isolate and (hopefully) fix the bug.

git diff 67bc4c8026c2b2875997ca6b4dcd56cd56882d6c^ 67bc4c8026c2b2875997ca6b4dcd56cd56882d6c

And there it is. Staring us right in the face. The problem is, of course, that we are using ‘=‘ instead of ‘==‘ in our conditional.

Now issue:

git bisect reset

to return to the current branch on the most recent commit, and fix your bug.