by Leon Rosenshein

Git Bisect and Fruit

What do source code management and splitting things in half have in common? git bisect. Remember the murder mystery @andrew.gemmel wrote about? That was the story about how a simple change to a unit test ended up periodically killing the ssh-agent. What he didn't talk about was how we narrowed things down to that commit so we could find the problem.

To do that we used git bisect. If you're ever trying to figure out exactly which commit changed the behavior of your repo from A to B then git bisect is your friend. It's actually pretty simple. You tell git you want to do a bisect with git bisect start, you mark the current revision as good or bad with git bisect good|bad, then you identify the other known case with git bisect bad <sha>. From that point on, git is driving. It will find the middle revision between the two extremes and check it out for you. You then decide if things are good or bad at that revision and let git know with git bisect good|bad as appropriate. git will then bisect the appropriate side of the current revision, check out the middle, and wait for you to tell it the status. The process continues until you've arrived at the revision that caused the repo to go from the good state to bad. Once you know where the problem is you stop the bisect with git bisect reset. And if you can write a simple script to decide if things are good or bad you can even replace the iterative part with git bisect run <script> <args>. Pretty simple and pretty powerful. There are lots of other options, so check them out.

But what has this got to do with fruit you ask? Well, one type of fruit is squash, and squash can help or hinder your bisect. When looking at changes on the main branch, squashing commits (which we do) means that every PR that lands is a single commit, regardless of how many commits it took on the branch to get there. This makes the git history more manageable, ideally means each commit is a working functional change/addition, and bisect has many fewer commits to deal with.

However, there's a tradeoff. Because all of those commits are squashed into a single commit, the code changes involved can be pretty complicated. And in that case when you finally bisect down to the commit that caused the change you may find there are lots of files/chunks that you need to look at to figure out what happened. In that case it might have helped if you had all those individual commits.

If you find yourself in that situation then once you have identified the commit you care about, see if the branch that created it is still around. If it is then you can go to that branch and further bisect since it will have all the individual commits. If not, you're left to wade through all the code and use your deductive reasoning to figure out what happened.

And that's how git, bisect, and fruit are related.