Skip to content
C Codeloom
Git

Git Bisect Tutorial: Find the Bad Commit Fast

Use git bisect to binary-search through history and pinpoint the commit that introduced a regression, with manual and automated examples.

·3 min read · By Codeloom
Intermediate 8 min read

What you'll learn

  • How binary search applies to commits
  • Running git bisect manually
  • Automating bisect with a script
  • Skipping broken commits
  • Avoiding common bisect mistakes

Prerequisites

  • Comfortable with git log and checkout

What and Why

When a regression sneaks in, you might know it worked last month and broke today. git bisect performs a binary search across history to find the exact commit that introduced the problem. With a clean repo and a reproducible test, you can isolate a single commit out of thousands in just a few steps.

Mental Model

Tell git two commits: one good, one bad. Git checks out a commit halfway between them. You run your test and mark the result. Git narrows the range. Eventually one commit is left, and that is the culprit.

bad <----------|---------|----------|---------> good
            mid1
                        mid2
                                  mid3
                                        found
Bisect halves the search

Hands-on Example

Manual flow.

git bisect start
git bisect bad                # current HEAD is broken
git bisect good v1.4.0        # last known good tag

# git checks out a midpoint
./run_tests.sh
git bisect good               # or: git bisect bad

# repeat until git prints the first bad commit
git bisect reset              # return to your branch

Automated flow. Provide a script that exits 0 if the commit is good and non-zero if bad.

# check.sh
#!/usr/bin/env bash
set -e
npm install --silent
npm test --silent -- --run path/to/regression.test.ts
chmod +x check.sh
git bisect start HEAD v1.4.0
git bisect run ./check.sh

Skip commits that cannot be tested, like ones that fail to build.

git bisect skip

A real session might end like this.

72 revisions left to test after this (roughly 7 steps)
[abc123] feat: add cache layer
...
The first bad commit is:
commit a1b2c3d4
Author: Sam <sam@example.com>
Date:   Wed Mar 5 11:02:33 2026

    refactor: invalidate cache on user update

You now know exactly where to look. Review the diff with git show a1b2c3d4 and write a regression test before fixing.

Common Pitfalls

  • Marking commits wrong. One incorrect good or bad will lead bisect to the wrong place. Re-run if you suspect a mistake.
  • Forgetting to reset. Always git bisect reset to leave a clean working tree.
  • Inconsistent reproduction. If the bug is flaky, bisect amplifies the flake. Stabilize your test first.
  • Running expensive setup at every step. Cache builds or use git bisect run with a quick check that only runs the smallest necessary suite.

Practical Tips

  • Use exit code 125 in your script to signal “untestable” so git skips that revision.
  • Combine bisect with git worktree to keep your main checkout untouched.
  • Pair bisect with git log --oneline --grep=regex to narrow the suspect range before you start.
  • When the bad commit is a merge, bisect into the merged branch with git bisect --first-parent if you want to ignore feature internals.
  • Document the bisect result in the bug ticket. It saves the next person hours.

Wrap-up

git bisect turns “somewhere in 800 commits” into “one specific change” in a handful of steps. The key is a reliable test and honest answers about good and bad. Once you have those, bisect does the math, and your debug time drops from days to minutes. Add the bisect run automation to your toolbox and you will reach for it instinctively the next time something breaks.