Find Bugs Fast with Git Bisect

A new bug shows up in production. Users are complaining. You look at the code and nothing seems obviously wrong. You know it worked last week but now it doesn’t. What do you do?

The common approach is a mix of guesswork and manual labor. You start checking out old commits one by one. You checkout yesterday’s main branch. Rebuild the app. Test. Still broken. You checkout the commit from two days ago. Rebuild. Test. It works. So the bug was introduced sometime yesterday. Now you start looking through all of yesterday’s commits trying to spot the problem.

This process is slow and frustrating. It’s frustrating because it feels dumb. Your brain is a powerful pattern matching machine and you are using it for a linear search. There is a much better way.

The Systematic Way

Computers are very good at systematic searching. Git gives you a tool to leverage that power. It’s called git bisect. It uses a binary search algorithm to find a specific commit in your history. All you have to do is tell it whether a given commit is good or bad.

Binary search is fast. If you have 100 commits to check it won’t take 100 tests. It will take about 7. If you have 1000 commits it will take about 10. It quickly narrows down the search space until it isolates the single commit that introduced the change.

How to Use Git Bisect

The process is simple. You start a bisect session you give it one known bad commit and one known good commit and then you start testing.

First start the session. You are usually on a broken branch so HEAD is a good place to start.

# Start the process
git bisect start

# Mark the current commit as bad
git bisect bad HEAD

Next you need to tell Git a commit where you know the code worked. This could be a tag from your last release or just a commit hash from a week ago.

# Mark an old commit as good. You can use a tag or a commit hash.
git bisect good v1.2.0
# or
git bisect good a1b2c3d4

Now the search begins. Git will checkout a commit exactly in the middle of your good and bad range. It will tell you something like this.

Bisecting: 675 revisions left to test after this (roughly 10 steps)

Your job is to build and test your application at this commit. Once you know if the bug exists you tell Git.

If the bug is still there you run:

git bisect bad

If the bug is gone you run:

git bisect good

Git will then checkout another commit halfway between the new good and bad range. You repeat the process. Test and then tell Git if it’s good or bad. You keep doing this until Git finds the answer.

After a handful of steps Git will print out the full commit hash and details of the first bad commit. It has found the source of your bug.

a9b8c7d6e5f4g3h2i1j0 is the first bad commit
Author: Alex Smith <alex@example.com>
Date:   Mon Oct 24 10:30:15 2023 -0500

    Refactor user authentication service

 ...commit details...

Once you have your answer you should clean up and end the bisect session. This will return you to the branch you were on when you started.

git bisect reset

That’s it. You have found the exact change that caused the problem in a few minutes instead of a few hours.

The manual process is fast but it can be even faster. If you have an automated test that can detect the bug you can have git bisect run it for you.

The command is git bisect run. You give it a script or a command to execute. Git will run this command on every step. If the script exits with code 0 Git marks the commit as good. If it exits with any other code (like 1 for a test failure) Git marks it as bad.

Imagine you have a test suite that fails when the bug is present. You could run.

git bisect run npm test

Or maybe you have a specific script to check for the problem. You could write a small shell script called run_test.sh.

#!/bin/bash

# build the project
./gradlew build

# run the specific command that fails
./my-app --check-feature

# The exit code of the last command will be used by git bisect

Make it executable with chmod +x run_test.sh. Then start the automated search.

git bisect start HEAD v1.2.0
git bisect run ./run_test.sh

Now you can go get a coffee. Git will perform the entire search on its own and present you with the culprit commit when it’s done. This is incredibly powerful. It turns a debugging session into a single command.

To make this work you need tests. Not necessarily a full unit test suite but some scriptable way to confirm if the bug exists. The time you spend writing a small test script is almost always less than the time you would spend manually bisecting.

Think about the last hard to find bug you chased.

— Rishi Banerjee
September 2025