Git Bisect
Learn how to use the git-bisect command to make life easier.
We'll cover the following
Git bisect mode
The git bisect
method is the kind of tool we’ll use about once every six months, but when we use it, we’ll be totally thrilled that it exists.
Isolation commits for debugging
The git bisect
is indicated when something has gone wrong in our code, and we believe it to be the result of a code change but we cannot isolate which change resulted in the problem. The git bisect
's goal is to isolate the commit where the change occurred.
Note: Use
git bisect
to track down mysterious failures in our code when we have no idea how they were inserted.
We start using git bisect
with two commands:
$ git bisect start
$ git bisect bad
The first command puts Git into what we’ll call bisect mode, and the second command says that the current Git snapshot is bad, meaning it contains the behavior we’re trying to fix.
We then switch the Git snapshot to the secure hash algorithm of a previous commit that we believe is good because it doesn’t have the behavior. And we tell Git that branch is good. For example, we’d use this if we’ve determined that SHA 34ace43
is good:
$ git checkout 34ace43
$ git bisect good
We can combine those into one command, git bisect good 34ace43
.
Git advantages
Git now does something really neat. It derives a straight line of commits between the good one and the bad one, picks the middle of that line, and checks itself into that commit. We’ll see some commentary on the console explaining how many commits are in the line and roughly how many steps Git expects the bisect to take.
Our job is to do whatever we need to in the newly entered commit to determine if it is “good” or “bad” based on whether the incorrect behavior exists. Based on that, we enter either git bisect good
or git bisect bad
. (If we really can’t tell, we can do git bisect skip
).
Git now has enough information to know that the bad change was in one-half of the commits. If we said the commit was bad, then the change was in the first half of the commits; if we said it was good, then the change had to come after. Git splits the narrowed-down list of commits in half and checks out the middle commit.
We repeat our checks until eventually, we can isolate a change where the beginning state is good and the end state is bad. Ideally, inspecting the commit list of the commit with that change will give us a hint as to what’s causing the behavior, since one of those changes is likely the cause. This process can save us hours.
Encapsulation with git bisect
Furthermore, if we can encapsulate whatever test we’re running against our codebase in a script that follows the Unix convention of returning a nonzero value on failure, we can pass that script to git bisect
and Git will automatically do the good/bad thing for we based on the result of the script. The syntax is of the following form:
$ git bisect run my_script
We note in passing that whichever tool we’re using to run our tests has this behavior, so git bisect run rspec
should work, though it’ll probably be a little on the slow side.
For the full git bisect
effect, a few things need to be true:
-
The problem needs to have been caused by a code change, not a change in our environment.
-
We need to be able to reliably trigger the problem.
-
It helps if our commits are relatively small and if the system is in a loadable and executable state after each one.
That said, when this works, it can work in big ways.
Get hands-on with 1400+ tech skills courses.