How to Git Bisect your Project
May 16, 2017Nicolas Miret3 min read
Over my last working year, I have worked on two big projects, both more than 18 months old with several scrum teams working on it. And both facing a few regressions in production each week.
Although I knew it existed and how it worked, I was not aware of the utility of git bisect and had never used it until a few weeks ago. Following a recommendation from the lead developer of my project, I started to use it to solve the regressions we were facing. And I feel like it may be the best way to do it.
You will have the lines of code which introduced the regression in less than 10 minutes. Git bisect allows you to go through 1000 commits in 10 iterations; as an indication, in my current 3-4 developers team, 1000 commits represent about 3 months of work.
Moreover, you will be able to find the dev who introduced the code. If you can reach them:
- You will easily have the context of why this buggy code was introduced, pointing out what you should be careful not to break while solving the bug
- You will help them progress. Finding out that some code you wrote was buggy because of this precise side effect, and that this was the best way to do it, is a very efficient way to get better.
- Most of all, you will be able to identify what information they lacked not to do this mistake, and thus which action to take to prevent similar regressions from happening.
Having the code and the context will help you a lot to find a solution to fix the bug.
The idea is really simple. Starting from two commits, one where the feature worked, and a more recent one with the feature broken, git bisect will perform a dichotomy to find the commit introducing the regression.
In practice, check out the current version of your code and start bisecting:
git bisect start
Since the feature is currently broken, inform git that this version contains the buggy commit:
git bisect bad
You will now need to find a state where the feature worked. It may be an older reliable release, or you may as well just go through your history to find a maybe one or two months old commit with the feature working.
Once you found it, mark this version as reliable:
git bisect good v2.1.13
git bisect good e627db2fc0a8ff1da6a67b5482c3f56dbedfaba1
The bisection will now actually start. Git checks out the commit in the middle of these two commits and you simply need to build your code and check whether the feature works or not. Indicate the result with git bisect good or git bisect bad and iterate. After a few iterations (git prompts you the number of required iterations after each step), you will have your faulty commit!
For more details on the options of the git bisect command, refer to the official git documentation
NB: This is one more reason for making usable (i.e. with the application build working) and unitary commits. Without it, git bisect will be either harder to use or less useful, since finding out the faulty lines in a big commit might not be easy.
My personal story
To illustrate my point, let me give you an example where the git bisection helped me. The regression I had to solve was a 15 pixels margin missing under the images and title of a given page:
A naive solution could have been to simply add a margin-bottom to the div containing those pictures. The regression would be solved, but we would have no idea of what caused it, and if it (or a similar one) would happen again.
Using git bisect, I found out that it was introduced about a month earlier. The margin-bottom still existed, but the property display: inline-block; had been removed from the tag under the image, and thus the margin no longer applied. The css class applied to this tag being shared in the entire website, it was clear to me that the developer had changed it to improve another page design but forgot to check if it broke something on the images page. I could therefore move the margin-bottom from the tag, where it was no longer needed, to the div containing the image and the text.
Yet, I checked with him, and it appeared that my hypothesis was completely wrong. He did check the broken page, but since a missing margin does not catch the eye, he didn’t notice the regression. The fix was still valid, but we learnt something else from this talk: to properly test the design of a page, one should compare the design before and the design after, to make sure that the changes only affect the desired parts.
As illustrated by this example, git bisect will allow you to quickly find the fix to the regressions you may be facing. But what makes it truly valuable is that it will also give you the root causes of these regressions, helping you to find the right actions to make sure that they won’t happen again.