very helpful lioness

Using Git bisect to figure out when brokenness was introduced

Sun, 10/02/2011 - 14:35 -- webchick

I did a fresh installation of Drupal 8 this morning and came across a bit of ugliness: an ugly grey border on the home page, caused by an empty div being inserted into the page:

Default front page showing a mysterious empty, grey-bordered box

My last fresh install of Drupal 8 was about a week ago and didn't have this problem. I didn't relish the idea of going through all of the commits since then one-by-one to figure out where this bug was introduced.

Enter the git bisect command! The git bisect command works by performing a "binary" search between one state of the code and the other in order to find, by process of elimination, where a given problem was introduced. It's quick, it's easy, and by golly it just works!

Here's how to use git bisect, step-by-step!

Step 1: Find a commit where things were working.

Have a look through the git log for a commit from around the time you know things were last working, such as http://drupalcode.org/project/drupal.git/commit/fd0a623f478e335794e09c41....

Confim that this commit actually works ok by switching your checkout to it instead:

(Tip: you only need to reference the first 5-6 characters of the commit hash; you don't need the entire thing... Git is smart and will figure it out!)

$ git checkout fd0a623f

Note: checking out 'fd0a623f'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b new_branch_name

HEAD is now at fd0a623 - Patch #1201024 by pillarsdotnet: drupal_realpath() should describe when it should be used.

Now refresh your Drupal 8 site in your browser . Yay! No more ugly border. So we know that this version of the code, at least, was working okay. Progress!

Step 2: Find a commit where things are not working.

(Tip: Normally, this will just be '8.x' or whatever branch you're working on where you found the problem, but since I want this tutorial to work even months or years from now, we'll go with this route.)

Next we need to know the current commit hash, where things are not working so good. That would be http://drupalcode.org/project/drupal.git/commit/256d85044583970a2d39e6d9....

Confirm this by doing:

$ git checkout 256d85

Previous HEAD position was fd0a623... - Patch #1201024 by pillarsdotnet: drupal_realpath() should describe when it should be used.
HEAD is now at 256d850... Issue #1011614 by catch: Fixed Theme registry can grow too large for MySQL max_allowed_packet() and memcache default slab size.

...and refreshing the page again. That ugly border is back again. Ick!

Step 3 - N: Use git bisect to find the problem commit

Great. So we know where it was working, and we know where it isn't anymore. Time for some fun!

To begin, we need to start git bisect and then give it the "known good" place, and the "known bad" place.

$ git bisect start
$ git bisect good fd0a623
$ git bisect bad 256d850

Bisecting: 28 revisions left to test after this (roughly 5 steps)
[68c0c8c6359961cbef832398c4ddab0fe2f17083] Issue #1238258 by kiamlaluno, izmeez: Change 'Track page visits' to 'Page visits'.

Git bisect looked at all of the commits between fd0a623 and 256d850, picked the middle one, and switched the current checkout to that instead.

Now, we need to figure out if the code in commit 68c0c8c has the same issue or not. Reload the page. Hey, the ugly border is gone again!

Tell Git about the good news, and it will start the next search, this time at the halfway point between commit 68c0c8c (new known good) and 256d850 (known bad):

$ git bisect good

Bisecting: 14 revisions left to test after this (roughly 4 steps)
[03b443e8f5043b6e8c3a743ad01a3db9d663ad3c] Issue #1123092 by michaellenahan, varunarora: Fixed user-profile.tpl.php doc has confusing/misleading first paragraph.

Refresh the page. Ewww. Border's back again. That's no good. However, we did manage to find a new "known bad" state. Let's tell Git about it so it can give us a new version to try:

$ git bisect bad

Bisecting: 6 revisions left to test after this (roughly 3 steps)
[e217c4ef1bf06ad75bf6124b9af520195f212001] Issue #1291458 by arithmetric: Fixed Database::getConnection mentions short-lived fixed bug and shouldn't.

You know the drill now. Reload. Border gone. Bisect good!

$ git bisect good

Bisecting: 3 revisions left to test after this (roughly 2 steps)
[08b9bd41723a0a23687c59033c15d66c1840b4f3] Issue #918808 by moshe weitzman, Damien Tournoud, dww: Standardize block cache as a drupal_render() #cache.

Reload. Border's back. BAD!

$ git bisect bad

Bisecting: 0 revisions left to test after this (roughly 1 step)
[9763ca906a6229125dfbe1b56956405457d55892] Issue #1290512 by droplet: Fixed Seven: remove duplicated css.

One last time, reload. Border's gone. GOOD!

$ git bisect good

08b9bd41723a0a23687c59033c15d66c1840b4f3 is the first bad commit
commit 08b9bd41723a0a23687c59033c15d66c1840b4f3
Author: Nathaniel
Date: Thu Sep 29 12:29:59 2011 +0900

Issue #918808 by moshe weitzman, Damien Tournoud, dww: Standardize block cache as a drupal_render() #cache.

:040000 040000 493cba4b1f84c0e907a37f5f4e40d3576bb84785 7763c1bb6f7e4e7b1296863b5df945f5b1760f67 M modules

BAM! By process of elimination, we've just found our problem commit! It was from pesky old issue #918808. Time to update the issue with a pointer to the bug it introduced (and vice-versa).

Step 4: Get back to a working state

Once you're all finished up, run these commands to end your git bisect session and get back to the normal 8.x branch:

$ git bisect reset

Previous HEAD position was 9763ca9... Issue #1290512 by droplet: Fixed Seven: remove duplicated css.
HEAD is now at 256d850... Issue #1011614 by catch: Fixed Theme registry can grow too large for MySQL max_allowed_packet() and memcache default slab size.

$ git checkout 8.x

Switched to branch '8.x'

Now you're back in business to review more 8.x patches! w00t!

Awww, yeah!

We've successfully deduced where a problem was introduced in about 3 minutes. Sifting through commit logs and trying to revert patches on an ad-hoc basis can take 10 times that or more. Let's say it together now, Git bisect rules!! :D



Submitted by Anonymous (not verified) on

Git bisect rules!

Submitted by Bernhard (not verified) on

thanks for providing that url to us, looks very interesting to me. Me and my friends from the university talked about exactly that topic last week in Hamburg

Thanks for the great write-up! I've run into plenty of situations in which git bisect would have really come in handy, so I bet it's not long until I put this walkthrough to use!

git bisect is great. And it is another reason for caring about the project history (I mean the commit history in this context):

  • don't put logically unrelated changes in the same commit;
  • don't mix functional changes with cosmetic changes;
  • attribute changes to the original authors, so you know whom to ask about the change causing the problem; and they also take the blame :)

Those simple rules are generic but they have the side effect of making bisecting ever more effective.


I'm a big fan of it, especially if it's a bug like this that isn't dependent on the database. I've used it combined with drush site-install to reset the site after each bisect, but it's always painful if you have to re-import a huge DB from a production site.