Back
GitoryxGitoryx
Intermediate11 min read

Git Bisect: Find the Commit That Broke Your Code

git bisect uses binary search to pinpoint the exact commit that introduced a regression. Instead of checking hundreds of commits manually, it narrows the culprit down in logarithmic time. This guide shows you how — from the basics to full automation.

The Problem

The bug is real. You reproduced it. But your last 200 commits are a black box — you have no idea when it crept in. Checking out commits one by one would take hours. There has to be a better way.

git bisect uses binary search to find the exact commit that introduced a regression in O(log n) steps. For 200 commits, that's at most 8 checkouts. It's one of Git's most powerful and underused debugging tools — and knowing it sets senior developers apart.

Common mistakes developers make with this:

  • Forgetting to mark a commit as `bad` or `good`, leaving bisect stuck
  • Quitting bisect without running `git bisect reset`, leaving a detached HEAD
  • Starting bisect without a reliable way to test whether the bug exists
  • Using bisect on a repository with many merge commits without `--first-parent`
  • Running bisect with uncommitted changes, causing test interference

Gitoryx: Gitoryx highlights the bisect range on the commit graph, showing which commits have been marked good, bad, or are still in the search window — so you always know where you are in the process.

What is Bisect: Find the Commit That Broke Your Code?

git bisect performs a binary search through your commit history to find the specific commit that introduced a bug. You mark known-good and known-bad commits, and Git checks out the midpoint for you to test — halving the search space with each step.

Step-by-Step Guide

1

Start the bisect session

Enter bisect mode with `git bisect start`. Git will track the search state until you reset.

bash
git bisect start

# You should have a clean working tree before starting.
# Check with:
git status
# If there are uncommitted changes, stash them first:
git stash

Always start bisect with a clean working tree. Uncommitted changes can interfere with builds or tests at intermediate commits.

2

Mark the bad commit

Tell Git which commit is known to be broken. Usually this is HEAD — your current state.

bash
# Mark the current commit (HEAD) as bad
git bisect bad

# Or mark a specific commit as bad:
git bisect bad a3f1c2d
3

Mark a known-good commit

Tell Git a commit where the bug did NOT exist. This is the other end of the search range. Use a tag, a commit SHA, or a relative ref.

bash
# Mark a tag as good (last known release without the bug)
git bisect good v2.1.0

# Or use a commit SHA:
git bisect good 9b2e4f1

# Or use a date-based ref:
git bisect good HEAD~30   # 30 commits ago

The further back your good commit is, the more commits git bisect will search through — but even 1000 commits only needs ~10 steps.

4

Test each checkout and mark it

Git will checkout the midpoint between good and bad. Run your test or reproduce the bug manually, then mark the result.

bash
# Git checks out a commit and tells you how many steps remain:
# Bisecting: 7 revisions left to test after this (roughly 3 steps)
# [c8a3f1d] Add user avatar upload

# Run your test — for example:
npm test
# or manually reproduce the bug, then mark:

# If the bug EXISTS at this commit:
git bisect bad

# If the bug does NOT exist at this commit:
git bisect good

# Git will immediately checkout the next midpoint.
# Repeat until bisect identifies the culprit commit.
5

Read the result

When bisect has narrowed the range to a single commit, it reports the first bad commit with full details.

bash
# Git output when bisect is complete:
# a7b3c2d1e is the first bad commit
# commit a7b3c2d1e
# Author: Jane Smith <jane@example.com>
# Date:   Tue Apr 8 14:32:11 2025 +0200
#
#     Refactor authentication middleware
#
# :100644 100644 abc123 def456 M  src/middleware/auth.js

Once you know the commit, use `git show <sha>` to inspect exactly what changed.

See this workflow in Gitoryx — Gitoryx demo

See this workflow in Gitoryx. The commit graph highlights the bisect range in real time — green for good, red for bad, yellow for the current test commit.

Free download
6

Exit bisect and restore your branch

Always run `git bisect reset` when done. It returns you to your original branch and HEAD, and clears all bisect state.

bash
git bisect reset

# Output:
# Previous HEAD position was a7b3c2d Refactor authentication middleware
# Switched to branch 'main'

Never forget `git bisect reset`. Forgetting it leaves you in a detached HEAD state with bisect log still active, which confuses subsequent git commands.

7

Automate with a test script

If you have an automated test that reproduces the bug, bisect can run it automatically on every commit. Pass any shell command that exits with `0` for good and non-zero for bad.

bash
# Start bisect
git bisect start
git bisect bad HEAD
git bisect good v2.1.0

# Let bisect run your test automatically on each commit:
git bisect run npm test

# Or a custom script:
git bisect run ./scripts/check-regression.sh

# Git will run the script at each midpoint, mark good/bad
# automatically, and report the first bad commit.
# Exit code 0  → good
# Exit code 1-124 → bad
# Exit code 125 → skip this commit (untestable)

Exit code 125 tells bisect to skip a commit (e.g., it doesn't compile). Bisect will try the next one instead.

8

Skip untestable commits

Some commits may not compile or may be untestable (merge commits, broken builds). Skip them with `git bisect skip` and bisect will work around them.

bash
# Skip the current checkout if it can't be tested:
git bisect skip

# Skip a range of commits:
git bisect skip v2.3.0..v2.3.5

# Skip a specific commit:
git bisect skip a3b2c1d

Common Mistakes to Avoid

Forgetting git bisect reset

The most common bisect mistake. Without `git bisect reset`, you remain in a detached HEAD state. Future git commands behave unexpectedly, and the bisect log persists.

Fix: Always finish a bisect session with `git bisect reset`, whether you found the culprit or not. Put it in your muscle memory.

Starting without a reproducible test

Bisect is only useful if you have a reliable way to determine whether a commit is good or bad. If your test is flaky, you'll mark commits incorrectly and get wrong results.

Fix: Before starting bisect, verify you can consistently reproduce the bug. Write a failing test or a shell script that reliably detects the regression.

Picking a good commit that's too close

If your known-good commit is only 10 commits back, bisect is overkill. The power of bisect is finding bugs across hundreds or thousands of commits.

Fix: Use tags or releases as your good starting point. `git bisect good v1.0.0` is ideal when you know the bug didn't exist in the previous release.

Not using --first-parent on merge-heavy repos

On repos with many merge commits, bisect may step into topic branch commits that look unrelated to the bug, producing confusing results.

Fix: Use `git bisect start --first-parent` to restrict bisect to the main branch lineage only.

Gitoryx — visual Git client for macOS, Windows & Linux
GitoryxGitoryx — macOS, Windows & Linux

Debug Faster with Bisect in Gitoryx

  • The commit graph highlights the bisect range in real time — green for good, red for bad, yellow for the current test commit.
  • Mark commits as good or bad directly from the graph with a right-click — no commands to type.
  • Gitoryx shows the estimated steps remaining at each bisect point.
  • View the full diff of each bisect commit inline — without leaving the app.
  • One-click `bisect reset` is always visible in the bisect panel so you never get stuck in a detached HEAD.
Download Gitoryx — FreemacOS · Windows · Linux · No subscription

Frequently Asked Questions

What is git bisect used for?

git bisect is used to find the exact commit that introduced a bug or regression. It uses binary search through your commit history, checking out the midpoint between a known-good and known-bad commit, until it identifies the first bad commit.

How fast is git bisect?

git bisect is logarithmically fast. To search 1000 commits, it takes at most 10 steps. To search 1 million commits, it takes at most 20 steps. Each test cuts the remaining search space in half.

What do 'good' and 'bad' mean in git bisect?

'bad' marks a commit where the bug exists. 'good' marks a commit where the bug does not exist. Git searches for the earliest 'bad' commit between these two points.

Can git bisect be automated?

Yes. Use `git bisect run <command>` to run a test script at each bisect step automatically. The script should exit with 0 if the commit is good, non-zero (1–124) if bad, and 125 to skip an untestable commit.

What is git bisect skip?

`git bisect skip` tells Git to skip the current commit because it cannot be tested (e.g., it doesn't compile). Bisect will move on to the next commit in the search range.

What happens if I forget git bisect reset?

You will be left in a detached HEAD state with bisect mode still active. Run `git bisect reset` at any time to restore your original branch and HEAD position.

Can I use git bisect with a merge-heavy repository?

Yes, but use `git bisect start --first-parent` to restrict the search to the main branch lineage. This prevents bisect from stepping into side branches of merged pull requests.

How do I view the bisect log?

Run `git bisect log` to see the full history of markings during the current session. Run `git bisect visualize` to open gitk with the remaining candidate commits highlighted.

See it in action with Gitoryx

Everything in this tutorial is faster and clearer with a visual Git client. Gitoryx is free, runs natively on macOS, Windows, and Linux, and built for developers who want to move fast without breaking things.