“It worked yesterday, but it is broken today.” In any active software project, regression bugs are bound to slip in. Finding the exact commit that introduced a bug out of hundreds or thousands of commits can feel like searching for a needle in a haystack.
Instead of manually checking out commits one by one or spending hours analyzing code changes, you can use Git’s built-in debugging tool: git bisect.
In this article, we’ll explain how to use the binary search algorithm of git bisect to locate the origin of a bug in minutes.
1. How git bisect Works (Binary Search)
The git bisect command uses a Binary Search algorithm to navigate your git history.
Imagine you have a range of 100 commits, and you know the bug was introduced somewhere in between:
- Git checkouts the commit right in the middle (commit #50).
- You test the application at this point.
- If the code is broken, the bug was introduced in the first half (commits 1–49).
- If the code works, the bug was introduced in the second half (commits 51–100).
- Git splits the remaining range in half again (to commit #25 or #75) and checkouts that version.
By repeating this process, Git reduces the search space exponentially. Finding a bug among 100 commits takes at most 7 steps, and finding a bug among 1,000 commits takes at most 10 steps ($log_2(N)$).
2. Step-by-Step Manual Guide
Let’s walk through the manual process of identifying a bug.
Step 1: Start the Bisect Wizard
Initiate the bisect process:
git bisect start
Step 2: Set the Boundaries
Mark the current state (which has the bug) as “bad”:
git bisect bad
Next, identify a past version (a commit hash or a release tag like v1.2.0) where the feature worked perfectly, and mark it as “good”:
git bisect good a1b2c3d
Git will immediately check out a commit at the midpoint of this range.
Step 3: Test and Flag
Run your application or check your feature.
- If the bug is present:
git bisect bad - If the bug is absent (feature works fine):
git bisect good
Every time you enter a flag, Git checkouts the next test candidate.
Step 4: Locate the Culprit
Once the search space narrows down to a single commit, Git outputs the final result:
e5f6g7h8i9j0a1b2c3d4 is the first bad commit
commit e5f6g7h8i9j0a1b2c3d4
Author: Jane Doe <[email protected]>
Date: Mon Oct 15 12:00:00 2025 +0900
fix: change payment calculations
:040000 040000 8c1b2d3... 9e3f4a1... M src
You now know exactly which commit caused the regression! Once finished, exit bisect mode to return your repository to its original state:
git bisect reset
3. Automating the Search (git bisect run)
If your bug can be caught by an automated script or a test command (such as an integration or unit test), you can automate the entire bisect run.
git bisect start
git bisect bad
git bisect good v1.2.0
# Automatically run the test runner on every checkout step
git bisect run npm test
Git will check out, test, and label every step automatically, finishing the search in seconds.
Conclusion
The next time you encounter a regression bug, resist the urge to debug line-by-line. Instead:
- Define a known good point and a bad point.
- Launch
git bisect. - Narrow down the suspect commits using binary search (or automate it via
git bisect run).
It is a powerful tool to add to your debugging toolkit.
