← Back to list

Find the Bug with git bisect (Stop Guessing Which Commit Broke It)

Part 3 of the “Git & Version Control Mastery” series. The bug works in production but not on main. Somewhere in 400 commits, something…

Nazmul Hasan · 2026-06-20 07:01 · 0 claps · 3.6 min read
#github #debugging #version-control #developer-tools #productivity
Open on Medium ↗
Wiki topics: 💻 · Programming 🔓 · Open Source ⏱️ · Productivity

Find the Bug with git bisect (Stop Guessing Which Commit Broke It)

Part 3 of the “Git & Version Control Mastery” series. The bug works in production but not on main. Somewhere in 400 commits, something broke it. Git can find it in ~9 steps.

A bug report comes in: “the export feature is broken.” You check — yep, broken. But it was working two weeks and 400 commits ago. So which change broke it? The naive approach is to read through commits, or check out random old versions and test by hand, hoping to stumble onto the culprit. With hundreds of commits, that’s hours of tedious guessing.

There’s a tool that does this for you, systematically, in a handful of steps: git bisect. It's one of Git's most powerful features and one of the least used, because most developers don't know it exists. Let me change that.

Finding a bad commit by checking them one at a time is linear — 400 commits, up to 400 checks. Bisect is binary search — 400 commits, about 9 checks. Same answer, a tiny fraction of the work.

The Idea: Binary Search Through History

git bisect finds the exact commit that introduced a bug by repeatedly cutting the suspect range in half. You tell it one commit where things were good and one where they're bad; it checks out the middle commit and asks you to test. Based on your answer, it halves the range and repeats:

400 suspect commits
→ test the middle: bad?  → the break is in the first 200
→ test that middle: good? → the break is in the next 100
→ ... about log2(400) ≈ 9 tests total → the exact culprit

Nine tests instead of four hundred. That’s the power of binary search applied to your commit history.

The Manual Walkthrough

git bisect start
git bisect bad                 # the current commit is broken
git bisect good v1.2.0         # this old tag/commit worked
# Git checks out a commit halfway between. You test the feature, then:
git bisect good                # this commit works → bug is newer
#  or
git bisect bad                 # this commit is broken → bug is older
# Repeat. Git keeps halving until it announces:
#   <hash> is the first bad commit
git bisect reset               # return to where you started

Each good/bad answer halves the remaining suspects. After ~9 rounds on 400 commits, Git names the exact commit that introduced the bug — with its message, author, and diff. Now you know precisely what changed and why.

Fix #1: Automate It With a Test Script

The real magic: if you can write a command that exits 0 when good and non-zero when bad, Git will run the entire bisect for you, with zero manual testing:

git bisect start HEAD v1.2.0   # bad=HEAD, good=v1.2.0 in one line
git bisect run ./test-the-bug.sh

Where test-the-bug.sh is anything that detects the bug:

#!/bin/bash
# exit 0 = good (bug absent), exit 1 = bad (bug present)
npm test -- export.test.js     # or curl an endpoint, run a script, grep output

Git now checks out each midpoint, runs your script, reads the exit code, and walks straight to the first bad commit untouched. A 400-commit hunt becomes a single command and a coffee break. (Use git bisect skip for commits that won't build, so they don't poison the search.)

Fix #2: Make Bisect Effective With Good Commits

Bisect is only as good as your history. Two habits from elsewhere in this series make it shine:

  • Small, atomic commits (Part 4) — when bisect lands on the culprit, a small commit shows you exactly what broke. A giant commit just tells you “somewhere in these 800 lines.”
  • Commits that build and pass — if half your commits are broken work-in-progress, bisect can’t test them cleanly. Commits that each leave the code working make bisect reliable.

This is a concrete payoff for commit hygiene: clean history isn’t just pretty, it’s debuggable.

When Bisect Shines (and When It Doesn’t)

Reach for bisect when:

  • The bug is reproducible (you can reliably tell good from bad).
  • It regressed — it used to work and now doesn’t, so a “good” point exists.
  • The range is large enough that manual checking is painful.

It’s less useful for bugs that were always present (no good commit to anchor on) or that are intermittent (you can’t reliably answer good/bad). For everything else — the classic “it worked last release” regression — it’s unbeatable.

Putting It Together

  1. Mark a known good and bad commitgit bisect start / good / bad.
  2. Let Git halve the range, testing each midpoint.
  3. Automate with git bisect run <script> when you can script the test.
  4. Keep commits small and working so the result is precise and the search is clean.

The Takeaway

When a regression hides somewhere in hundreds of commits, your instinct is to start reading code or checking out random versions — hours of linear guessing. git bisect replaces that with binary search: about nine tests to pinpoint the exact commit, or zero manual tests if you can script the check. It's one of the highest-return tools in Git and almost nobody uses it. Learn it once, pair it with small clean commits, and the dreaded "which of these 400 changes broke it?" goes from an afternoon of detective work to a single command.

This is Part 3 of the Git & Version Control Mastery series. Next up: commit hygiene — how to write a history your future self (and bisect) will thank you for.

What’s the longest you’ve ever spent hunting for the commit that broke something? 👇


메타데이터
post_id
a17d4544c9cd
slug
find-the-bug-with-git-bisect-stop-guessing-which-commit-broke-it-a17d4544c9cd
url
https://medium.com/@najmul.hasan284/find-the-bug-with-git-bisect-stop-guessing-which-commit-broke-it-a17d4544c9cd
canonical_url
https://medium.com/@najmul.hasan284/find-the-bug-with-git-bisect-stop-guessing-which-commit-broke-it-a17d4544c9cd
author_url
https://medium.com/@najmul.hasan284
status
ok
fetched_at
2026-06-23 03:48:11