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.
Intermediate11 min readUpdated
What is git bisect?
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.
The short version
- 1Start:
git bisect start - 2Mark current broken state:
git bisect bad - 3Mark a known-good commit:
git bisect good <tag-or-sha> - 4Test each checkout and mark:
git bisect goodorgit bisect bad - 5Read the result: Git reports the first bad commit
- 6Exit:
git bisect reset
Why it matters
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.
Where it usually goes wrong
- Forgetting to mark a commit as
badorgood, 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
Git bisect, step by step
Step 1: Start the bisect session
Enter bisect mode with
git bisect start. Git will track the search state until you reset.Terminalgit bisect start# You should have a clean working tree before starting.# Check with:git status# If there are uncommitted changes, stash them first:git stashTip: Always start bisect with a clean working tree. Uncommitted changes can interfere with builds or tests at intermediate commits.
Step 2: Mark the bad commit
Tell Git which commit is known to be broken. Usually this is HEAD, your current state.
Terminal# Mark the current commit (HEAD) as badgit bisect bad# Or mark a specific commit as bad:git bisect bad a3f1c2dStep 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.
Terminal# 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 agoTip: The further back your good commit is, the more commits git bisect will search through, but even 1000 commits only needs ~10 steps.
Step 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.
Terminal# 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.Step 5: Read the result
When bisect has narrowed the range to a single commit, it reports the first bad commit with full details.
Terminal# 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.jsTip: Once you know the commit, use
git show <sha>to inspect exactly what changed.In Gitoryx: The commit graph highlights the bisect range in real time: green for good, red for bad, yellow for the current test commit.How it works Step 6: Exit bisect and restore your branch
Always run
git bisect resetwhen done. It returns you to your original branch and HEAD, and clears all bisect state.Terminalgit bisect reset# Output:# Previous HEAD position was a7b3c2d Refactor authentication middleware# Switched to branch 'main'Careful: Never forget
git bisect reset. Forgetting it leaves you in a detached HEAD state with bisect log still active, which confuses subsequent git commands.Step 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
0for good and non-zero for bad.Terminal# Start bisectgit bisect startgit bisect bad HEADgit 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)Tip: Exit code 125 tells bisect to skip a commit (e.g., it doesn't compile). Bisect will try the next one instead.
Step 8: Skip untestable commits
Some commits may not compile or may be untestable (merge commits, broken builds). Skip them with
git bisect skipand bisect will work around them.Terminal# 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
Mistakes to avoid with git bisect
- 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.0is 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-parentto restrict bisect to the main branch lineage only.
Git bisect in 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.
- 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 resetis always visible in the bisect panel so you never get stuck in a detached HEAD.
Free plan · no account required · macOS, Windows and Linux
Git bisect: 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 skiptells 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 resetat 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-parentto 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 logto see the full history of markings during the current session. Rungit bisect visualizeto open gitk with the remaining candidate commits highlighted.
Related reading
- How to Undo a Commit in Git (The Right Way)Tutorial · 10 min
- Git Changelog & Sprint Visualization: Track What ShipsTutorial · 13 min
- The Commit That Broke Checkout (Found With Git Bisect)Blog · 10 min
- How to Find Exactly When a Bug Hit Production (Using the Commit Graph)Blog · 9 min