Monday, February 22, 2016

Finding buggy code using git history and a binary search

Some bugs in software are easy to understand. Things like a null pointer exception are obvious and don't need a lot of context. But some bugs are more difficult. Some bugs just aren't obvious until you have the context of the change that was made that introduced the bug.

What I like to do when I'm hunting a bug down is to apply a binary search algorithm to my git history. This has two benefits:
  1. You're able to find the exact commit a bug is introduced in
  2. You've narrowed down the surface area of the code the bug could possibly be in

#1 above is important as it gives you the ability to reverse apply a patch and see if the bug goes away. If it works without breaking anything that's come to rely on that code it means that you've got a "quick fix" that can be issued to relieve the problem while you find a longer term solution.

Unless your team is a team of developers that goes dark #2 above is means you have found the handful of lines of code that contain the problem and the context of the code dependency. Simply seeing the inter-class dependencies may be enough to make an ambiguous bug make more sense. It's also a good place to look for violations of SOLID which make code less 'ible (maintainable, scalable, flexible, etc...).

So how do you accomplish this?

1. Find the starting point

Start with the git commit from your last release. Create a build from that and see if the bug reproduces. If not you've found your starting point. If it does reproduce and has been in the system a while, keeping going back release by release trying to find the commit of a build that does not contain the bug.

Hopefully you're tagging your releases or creating release branches.'

2. Use now as your ending point

3. Pick the mid point in time between your starting point and ending point

Using git log you:
  1. Get the hash of the commit closest to the mid point in time.
  2. Create a build using that commit
  3. Check to see if the bug reproduces
If the bug does reproduce you've got a new starting point: Repeat step 3 with the new starting point.

If the bug does not reproduce: Repeat step 3 with the new ending point.

Using this binary search you'll find the source commit of your bug fairly quickly (limited only by your build and validation time) and you'll have the context of the commit to fully understand the change that introduced the bug.

No comments:

Post a Comment