Join us on Facebook!
— Written by Triangles on July 17, 2020 • ID 82 —
A quick and managed way to understand which commit in your project’s history introduced a bug.
Imagine you've just found a weird behavior in your git-managed project, definitely a bug introduced somewhere during the development. The first reasonable thing to do is going back in the git history until you find the exact commit that caused the error, so that you can understand what went wrong exactly. You have two options:
The git bisect command is probably a better way to solve the issue. Like option 1), git bisect will search for the commit that introduced a bug. However, it will do it automatically for you without the need of calling
git checkout ... multiple times, manually. On top of that, git bisect performs the so-called binary search, much faster than the linear one. Let's see how the whole thing works!
The first thing to do is to find a relatively old commit that works. Take a look at your
git log command and pick a commit that is bug-free. It will take some trial and error at first. Eventually, you would end up with the following
git log scenario (comments on the right have been added by me):
31dfab2c Add new HTML template <---- this is buggy 055958a8 Include script.js c6c3c555 Fix macOS build [... lots of other commits here ...] 250e8add Fix master volume not parsed 8c563c01 Optimize UI rendering a545d17b Improve event handling <--- this is bug-free
In words, commit
31dfab2c is the most recent commit that contains the bug, while
a545d17b is one of the older commits that doesn't show the buggy behavior. You still don't now exactly which commit introduced the bug, but it definitely lies between the two above.
Enter the git bisect mode with the following command:
git bisect start
Nothing happens here, git bisect just started. Then tell git which commit is buggy and which one is bug-free with the following commands:
git bisect good [commit] git bisect bad [commit]
In our example that would be:
git bisect good a545d17b git bisect bad 31dfab2c
At this point git will automatically checkout to a certain commit: the git bisect operation has started.
Since you have changed the current commit, it's time to build and run your project. If the bug is still there, tell git this commit is bad with the following command:
git bisect bad
otherwise tell git this commit is bug-free with:
git bisect good
Once done, git will checkout to another commit until there are no more left to inspect. Repeat this point 3. until git will tell you to stop.
Eventually git will run out of commits to checkout: it will print out a description of the first bad one, for example:
Author: author <firstname.lastname@example.org> Date: Sun May 3 16:34:21 2020 +0200 Add new Import module :040000 040000 3bb45a00c6ad23c3a6205cfd19c6a4d6788fe219 91072ae36bf1faab4c465a2136e5c9b5c8169219 M src
This commit is the one that introduced the regression. You can study it to find the issue.
Once understood what's wrong, use
git bisect reset to put everything back on the original state before the git bisect operation. This will end the bisect session and bring you back to your original commit. You can also invoke this command anytime during a bisect operation in case you want to abort it.