Bisecting Bugs with Mercurial

While reading through the hg red bean book, I skipped over the “bisect” command thinking I’d never need it, or at least that it wouldn’t be worth the effort to figure it out. I used it yesterday for the first time. What was amazing was that it lead me to the source of the bug I was looking for, but in a completely unexpected location. It was a multi-threading bug, so I wasn’t too surprised that I had no idea where the bug was coming from.

The bisect command in Mercurial helps guide a binary search through your changeset history. There’s nothing magic about it. You could do something similar with CVS and piece a paper. It would just take longer because CVS updates are slower than hg updates. Furthermore, Mercurial understands the branchiness of the changeset history and can therefore be clever about pruning branches in the search. Also, in so far as you’re more likely to have done more and smaller commits in Mercurial than in CVS, you’re more likely to find a smaller changeset that caused your bug.

What happened
I started off with a changeset that I knew had the bug:

C:workspacesmyproject>hg summary
parent: 108:1d027969383d
...

I told hg that I wanted to start bisecting.

C:workspacesmyproject>hg bisect --reset

I told hg that we were starting with a changeset that exhibits the bug

C:workspacesmyproject>hg bisect --bad

I told hg the name of a changeset that I knew didn’t exhibit the bug (this could have been be revision 1 if I didn’t mind more iterations)

C:workspacesmyproject>hg bisect --good 86
Testing changeset 91:65c9a096775f (8 changesets remaining, ~3 tests)
14 files updated, 0 files merged, 0 files removed, 0 files unresolved

At this point, hg has updated my workspace to another candidate changeset. After running my tests, I tell hg that the bug isn’t in this changeset.

C:workspacesmyproject>hg bisect --good
Testing changeset 100:54c93f18a1f0 (4 changesets remaining, ~2 tests)
3 files updated, 0 files merged, 0 files removed, 0 files unresolved

At this point, hg has updated my workspace to another candidate changeset. After running my tests, I tell hg that the bug isn’t in this changeset. Note that it’s keeping a running estimate of how many more iterations there are.

C:workspacesmyproject>hg bisect --good
Testing changeset 101:fd58a298ee36 (2 changesets remaining, ~1 tests)
3 files updated, 0 files merged, 0 files removed, 0 files unresolved

Changeset 101 exhibits the bug, so I tell hg and hg tells me that we’ve found the culprit. (Yes…I caused the bug.)

C:workspacesmyproject>hg bisect --bad
The first bad revision is:
changeset:   101:fd58a298ee36
branch:      some_branch
user:        Ben Hall <ben.hall@intelliware.ca>
date:        Wed May 11 12:02:53 2011 -0400
summary:     Some comment.

I tell hg “atta boy”.

C:workspacesmyproject>hg bisect --reset

For further magic, if detecting the bug can totally automated via a script, you can automate the entire search.

p.s. Greg, I haven’t fixed the bug yet. But at least I know where it is.

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply