Have you ever found a bug in code and needed to know when it was first introduced? Chances are, whoever committed the bug didn't declare it in their Git commit message. In some cases, it might have been present for weeks, months, or even years, meaning you would need to search through hundreds or thousands of commits to find when the problem was introduced. This is the problem that
git bisect was built to solve!
git bisect command is a powerful tool that quickly checks out a commit halfway between a known good state and a known bad state and then asks you to identify the commit as either good or bad. Then it repeats until you find the exact commit where the code in question was first introduced.
This "mathmagical" tool works by leveraging the power of halving. No matter how many steps you need to get through, by looking at the halfway point and deciding if it is the new top or bottom of the list of commits, you can find any desired commit in a handful of steps. Even if you have 10,000 commits to hunt through, it only takes a maximum of 13 steps to find the first offending commit.
- commit 1 bad <> commit 10,000 good => commit 5,000 is bad
- commit 5,000 bad <> commit 10,000 good => commit 7,500 is good
- commit 5,000 bad <> commit 7,500 good => commit 6,250 is good
- commit 5,000 bad <> commit 6,250 good => commit 5,625 is bad
- commit 5,625 bad <> commit 6,250 good => commit 5,938 is bad
- commit 5,938 bad <> commit 6,250 good => commit 6,094 is good
- commit 5,938 bad <> commit 6,094 good => commit 6,016 is bad
- commit 6,016 bad <> commit 6,094 good => commit 6,055 is good
- commit 6,016 bad <> commit 6,055 good => commit 6,036 is bad
- commit 6036 bad <> commit 6055 good => commit 6046 is bad
- commit 6,046 bad <> commit 6,055 good => commit 6,050 is bad
- commit 6,050 bad <> commit 6,055 good => commit 6,053 is good
- commit 6,053 bad <> commit 6,055 good => commit 6,054 is good
So, the first bad commit of the 10,000 is commit number 6,053. With
git bisect, this would take a couple of minutes at maximum. I can't even imagine how long this would take to investigate crawling through each commit one at a time.
Using Git bisect
git bisect command is very straightforward:
$ git bisect start
$ git bisect bad # Git assumes you mean HEAD by default
$ git bisect good <ref> # specify a tag or commit ID for <ref>
Git checks out the commit in the middle and waits for you to declare either:
$ git bisect good
$ git bisect bad
Then the bisect tool repeats checking out the commit halfway between good and bad commits until you tell it:
$ git bisect reset
Advanced users can even write scripts that determine good and bad states as well as any remediation actions to take upon finding the specific commit. You might not use the
git bisect command every day of your life, but when you need it, it is a lifesaver.