---
title: A beginner's guide to GIT BISECT - The process of elimination
description: Learn how to efficiently find flawed git commits using git bisect, an automated tool that simplifies the debugging process. Follow our step-by-step guide.
---

[Blog ](https://www.metaltoad.com/blog)

# [A beginner's guide to GIT BISECT - The process of elimination](https://www.metaltoad.com/blog/beginners-guide-git-bisect-process-elimination)

 Written by [Metal Toad Staff](https://www.metaltoad.com/blog/author/metal-toad-staff) | Apr 19, 2012 12:00:00 AM

## What Is GIT Bisect and When Should You Use It?

Git Bisect finds the commit that introduced a bug via binary search. You do this by marking a known good and bad commit; Git then checks out midpoints until the first bad commit is identified. This can also be automated with git bisect run.

The slowest, most tedious way of finding a bad git commit is something we've all done before. You checkout some old commit, make sure the broken code isn't there, then checkout a slightly newer commit, check again, and repeat over and over until you find the flawed commit.

## Why Bisect Is Fast: Binary Search in Plain English

Bisect (binary search) is fast because it eliminates half of the remaining search space with every comparison, giving it **O(log n)** time complexity. Here's why this is so efficient:

Instead of checking elements one by one like linear search, bisect repeatedly divides the problem in half. In a sorted array of 1,000 elements, linear search might need up to 1,000 comparisons in the worst case, while bisect needs at most 10 comparisons (since 2^10 = 1,024).

Bisect leverages the sorted nature of the data. At each step, it compares the target with the middle element and can definitively eliminate either the left or right half based on that single comparison. This "divide and conquer" approach is fundamentally more efficient than examining elements sequentially.

Modern implementations also benefit from good cache locality since they access memory in a predictable pattern, and the working set of data shrinks rapidly with each iteration.

This logarithmic scaling means bisect remains incredibly fast even for massive datasets, making it one of the most important algorithms in computer science for searching sorted data.

Using `git bisect` is a much better way. It's like a little wizard that walks you through recent commits, asks you if they are *good* or *bad*, and narrows down the broken commit. In this blog post, I encourage you to create a fresh git repository and walk through each step. Hopefully, you'll gain an intrinsic understanding of `git bisect` by the end of the exercise.

### Pre-Flight Checklist: Clean Working Tree & Reproducible Test

1. #### Create an experimental git repository.
   
   Copy and paste the following lines:
   
   ```
   mkdir git_bisect_tests
   cd git_bisect_tests
   git init
   ```
2. #### Create a history of commits to play with.
   
   Copy and paste the following lines. This will create a commit history for a file called ‘test.txt’ that contains the opening lyrics to the childrens song “Row Row Row Your Boat”.
   
   ```
   echo row > test.txt
   git add -A && git commit -m "Adding first row"
   echo row >> test.txt
   git add -A && git commit -m "Adding second row"
   echo row >> test.txt
   git add -A && git commit -m "Adding third row"
   echo your >> test.txt
   git add -A && git commit -m "Adding the word 'your'"
   echo boat >> test.txt
   git add -A && git commit -m "Adding the word 'boat'"
   echo gently >> test.txt
   git add -A && git commit -m "Adding the word 'gently'"
   sed -i -e 's/boat/car/g' test.txt 
   git add -A && git commit -m "Changing the word 'boat' to 'car'"
   echo down >> test.txt
   git add -A && git commit -m "Adding the word 'down'"
   echo the >> test.txt
   git add -A && git commit -m "Adding the word 'the'"
   echo stream >> test.txt
   git add -A && git commit -m "Adding the word 'stream'"
   ```
   
   
   
   Output:
3. #### Find the bug in ‘test.txt’ file.
   
   Look at the contents of test.txt. There is a glaring error: the word ‘car’ is where the word ‘boat’ should be. That happened during our commit history – at some point, the commit of the word ‘boat’ was overwritten by the commit for the word ‘car’.

### The Experiment

1. #### Use git log to find a *good* commit, and a *bad* commit.
   
   First off, let’s try to find a commit that still had the word ‘boat’, and not the word ‘car’. Check out your git log:
   
   We know that the newest commit in the log is bad, so we will classify this as our *bad* commit. For the sake of simplicity, let’s say our *good* commit is the first commit we made for the word 'boat':
2. #### With a *good* commit, and a *bad* commit, we’re ready for the process of elimination – `git bisect`
   
   Git bisect is like a wizard: it guides you step by step through a process of elimination until you find the commit that broke your code. Once you type `git bisect start`, you have started the wizard and it won’t end until you type `git bisect reset`.
3. #### Start up the git bisect wizard
4. #### Let the git bisect wizard know of a *good* commit.
   
   In this case, it was the ‘Adding the word boat’ commit we picked above.
5. #### Let the git bisect wizard know of a *bad* commit.
   
   In this case, let’s use the very last commit in the repository, since we know that had the word ‘car’ in it.
6. #### Look at the contents of test.txt
   
   When we typed `git bisect bad` in this step, git bisect checked out an old commit for us – the commit halfway between the latest *bad* commit and the known *good* commit. This is how bisect works – it cuts the commit history down in halves until it finds the original bad commit.
7. #### The word 'car' is still there = BAD!
   
   This commit is still bad, so we tell bisect about how bad it is: `git bisect bad`
8. #### Look at the contents of test.txt again.
   
   Once again, git bisect checked out a new commit halfway between the latest *bad* commit and the known *good* commit.
9. #### The word 'boat' is there = GOOD!
   
   Now we see the word ‘boat’, so this is a *good* commit. Let’s let git bisect know how good it is: `git bisect good`
10. #### ALL DONE - The bad commit has been found!
    
    Plain as day, git reports back to you: “I found the first bad commit”
    
    You are now free to investigate the problem, notify the author, write patches, and take care of business.
11. #### To end your git bisect wizard, simply type git bisect reset

With `git bisect`, I've been able to narrow down broken code within a few seconds on repositories with a dozen developers adding several dozen commits per hour. I almost never use any other technique to find broken code.

## Picking Your “Good” and “Bad” Commits Strategically

When using `git bisect` to find a bug, choosing good "good" and "bad" commits strategically can dramatically reduce your search time. Here's how to pick them effectively:

### Start with Maximum Range

**Pick the furthest apart commits you're confident about:**

- **Bad commit**: Use the most recent commit where you know the bug exists (often `HEAD`)
- **Good commit**: Go back as far as you can to a commit you're certain was working

```
git bisect start HEAD v2.1.0  # Wide range for maximum efficiency
```

### Strategic Good Commit Selection

**Use stable reference points:**

- **Release tags** - These are usually well-tested
- **Merge commits** - Often represent completed, tested features
- **Commits before major changes** - If you suspect a particular feature introduction

```
# Good choices for "good" commitsgit bisect good v1.5.2        # Last known working releasegit bisect good main~50       # 50 commits back from maingit bisect good abc123def     # Commit before suspected feature
```

### Confidence Over Precision

**Better to be conservative than wrong:**

- If unsure whether a commit is good, test it manually first
- It's better to have a slightly smaller range with certainty than guess and mislead the bisect
- One wrong "good" or "bad" marking can send you down the wrong path entirely

### Consider Your Bug Type

**Match your strategy to the bug:**

- **Regression bugs**: Go back to last known working version
- **New feature bugs**: Start from before the feature was added
- **Performance issues**: Use commits with known performance benchmarks

### Use Git History Intelligence

```
# Find good candidate commitsgit log --oneline --graph main~100..maingit tag --list                           # See release tagsgit log --merges main~50..main          # Find merge commits
```

The key is maximizing your search range while maintaining absolute confidence in your boundary commits. A well-chosen range can turn a 100+ commit search into just 6-7 steps.

*Like this article? Check out our [top 5 Git tips and tricks](https://www.metaltoad.com/help/top-5-git-tips)*

Metal Toad is an [AWS Managed Services](https://www.metaltoad.com/services/aws-managed-services) provider. In addition to this article we recommend checking our article on [how to host a website on AWS](https://www.metaltoad.com/blog/how-host-website-aws-5-minutes) in 5 minutes.

[View full post](https://www.metaltoad.com/blog/beginners-guide-git-bisect-process-elimination)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Metal Toad Staff"
  },
  "dateModified" : "2025-09-09T23:28:30.200Z",
  "datePublished" : "2012-04-19T00:00:00Z",
  "headline" : "A beginner's guide to GIT BISECT - The process of elimination",
  "image" : {
    "@type" : "ImageObject",
    "height" : 359,
    "url" : "https://6104926.fs1.hubspotusercontent-na1.net/hubfs/6104926/git-bisect-blog-header.jpg",
    "width" : 686
  },
  "mainEntityOfPage" : "https://www.metaltoad.com/blog/beginners-guide-git-bisect-process-elimination",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60.0,
      "url" : "https://6104926.fs1.hubspotusercontent-na1.net/hubfs/6104926/social-suggested-images/6104926.fs1.hubspotusercontent-na1.nethub6104926hubfsMetal_Toad_Logo_orange_horizontal-50-1.jpg",
      "width" : 240.00002
    },
    "name" : "Blog"
  }
}
```