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.