The setting
Imagine you have to find the commit that broke something - among hundreds of commits.
What do you do? You can manually revert to the last known good commit, then check all the commits after. This can be tedious work, but of course can be automated - and basically this is what git bisect does.
Enter git bisect
Git bisect is a tool you shouldn’t need often - but when you need it, you need it bad. Bisect isolates the culprit commit with logarithmic efficiency by performing a binary search of the commits on your branch, dividing and conquering until only one commit remains.
Tell me more
The first steps
$ git bisect start # enter bisect mode |
At this point git bisect knows the commit range to check and tells us what to expect. It will start splitting the revision range [bad, good] in half and loading them up for you. It will checkout each revision and then ask you if the commit is good or bad. You answer git bisect good or git bisect bad and git will take care of the rest. It will use binary search to very quickly narrow down the offending commit.
It has already checked out 8aecfb4e3f7661b8df9145e6b20f9b555fbf8cd0 as the first candidate.
Let’s see it in action
$ git bisect good # this is still a working revision, we have to search further |
Can’t we automate it somehow?
Sure we can. Supose your app has tests to tell if the revision is good or bad. Then you can tell git bisect what to run for each commit to check if it’s good or bad judging by the command’s exit code the usual way (0 == ok, !0 == error)
$ git bisect start # enter bisect mode |
Git bisect will do the previous process but in a fully automated way: It will check out revisions, run your command (unit/functional tests, etc.) for each and judge if the commit is good or bad based on the exit code of your command, finally presenting you with the first bad commit in the range you initially specified.
Closing words
When you’ve found the offending commit, don’t forget to exit bisect mode and get back on your working branch:
$ git bisect reset |
Git bisect is a great tool for finding bugs in a long commit history, but of course it’s even better to have tests for everyting and having them run automatically for each commit with git hooks, and/or having a CI setup.