Skip to main content

Command Palette

Search for a command to run...

Git Bisect: Find Bugs Like a Detective

Learn: Git Bisect: Find Bugs Like a Detective

Updated
7 min readView as Markdown
T

Welcome to TopperBlog! 👋

I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.

🎯 What I Write About: • AI/ML Engineering & LLMs • Web3 & Blockchain Development
• System Design & Architecture • Interview Preparation (FAANG) • Freelancing & Remote Work • Modern Tech Stacks (Next.js, React, Rust, TypeScript) • Performance Optimization & Best Practices

💼 Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.

📚 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.

🌐 Let's connect and grow together in this amazing tech journey!

#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering

Git Bisect: Find Bugs Like a Detective 🔍

You know that special kind of panic when your boss walks over and says, "Hey, the login feature is broken in production"? Your heart sinks. Your palms sweat. You frantically think back through the last 47 commits, 12 merge conflicts, and that one time Dave pushed directly to main because "it was just a small fix."

Somewhere in those commits lurks a bug. A sneaky, production-breaking, career-questioning bug.

You could spend the next four hours playing commit roulette, checking out random SHAs and praying to the git gods. Or you could channel your inner Sherlock Holmes and use git bisect to hunt down that bug in about 10 minutes.

Let me tell you a story.

The Case of the Mysterious Memory Leak

Last year, I was working on a data processing service. Everything was fine on Friday. Monday morning? The application was eating RAM like Cookie Monster at a bakery.

We had 156 commits between "working fine" and "oh god why." My junior dev suggested we check each commit manually. I did the math: at 5 minutes per commit, that's 13 hours. I had a lunch meeting in 2 hours.

This is where git bisect became my best friend.

What the Hell is Git Bisect Anyway?

Think of git bisect as a binary search for your commit history. Remember binary search from CS 101? You're looking for a number in a sorted list, so you check the middle. Too high? Check the middle of the lower half. Too low? Check the middle of the upper half. Repeat until you find it.

Instead of checking 156 commits linearly (worst case: 156 checks), binary search needs only log₂(156) checks. That's about 8 commits.

Eight. Commits.

Your commit history is already sorted by time, and you know one end is good and one end is bad. Git bisect does the rest.

The Detective's Toolkit: How Git Bisect Works

Here's the basic workflow:

Step 1: Start the Investigation

git bisect start

You've just told git: "I'm about to play detective."

Step 2: Mark the Crime Scene

git bisect bad                 # Current commit is broken
git bisect good v2.1.0         # This old commit/tag was fine

You're establishing the boundaries. "The bug exists NOW, but it didn't exist at version 2.1.0."

Step 3: Let Git Do the Math

Git immediately checks out a commit halfway between good and bad:

Bisecting: 78 revisions left to test after this (roughly 6 steps)
[commit-hash-here] Refactored authentication module

Step 4: Test and Report

Now you test. Run your app. Check if the bug exists. Then tell git:

git bisect good    # This commit is fine
# OR
git bisect bad     # Nope, bug is here too

Git immediately jumps to the next strategic commit. Repeat until:

abc123def is the first bad commit
commit abc123def
Author: Dave <dave@company.com>
Date:   Fri Oct 13 16:45:00 2023

    Quick fix for edge case (YOLO)

FOUND YOU, DAVE.

Step 5: Clean Up

git bisect reset   # Returns you to where you started

Real-World Example: The Login Bug

Let's walk through that login bug I mentioned. Here's exactly what I did:

# Start the investigation
git bisect start

# Current HEAD is broken
git bisect bad

# Last week's release was fine
git bisect good release-1.4.2

# Git checks out a commit in the middle
# I test the login... it works!
git bisect good

# Git jumps to another commit
# I test... still broken
git bisect bad

# Git narrows it down
# Test... works
git bisect good

# Test... broken
git bisect bad

# After 7 tests total:
# 4f8a9c2 is the first bad commit
# Author: Dave (of course)
# "Simplified JWT validation logic"

The bug? Dave removed a null check because he thought it was "redundant." It wasn't.

Total time: 11 minutes. Including the time I spent making coffee.

The Nuclear Option: Automated Bisecting

Here's where it gets really cool. If you can write a script that returns exit code 0 for "good" and non-zero for "bad," git can bisect automatically:

git bisect start HEAD v2.1.0
git bisect run npm test

Git will run your test suite at each commit and automatically mark it good or bad based on the exit code. You can literally go get coffee while git does the detective work.

For our memory leak, I wrote a simple script:

#!/bin/bash
# test-memory.sh

npm start &
PID=$!
sleep 30

# Check memory usage
MEMORY=$(ps -o rss= -p $PID)
kill $PID

# Fail if using more than 500MB
if [ $MEMORY -gt 512000 ]; then
    exit 1
fi
exit 0

Then:

chmod +x test-memory.sh
git bisect start HEAD last-good-commit
git bisect run ./test-memory.sh

I went to lunch. Came back. Bug found. Dave apologized. All was right with the world.

Pro Tips from the Trenches

1. Skip Unbuildable Commits

Sometimes you hit a commit that doesn't even compile:

git bisect skip

Git will try a nearby commit instead.

2. Visualize Your Progress

git bisect visualize
# or
git bisect view

Shows you where you are in the bisect process. Helpful when you're deep in the investigation.

3. Save Your Bisect Session

Need to stop for a meeting? Your bisect state is saved. Just continue later:

# Git remembers you're mid-bisect
git bisect good  # Pick up where you left off

4. Use Descriptive Test Scripts

Your future self will thank you:

#!/bin/bash
# bisect-test-login.sh
# Tests if login works with valid credentials

curl -X POST http://localhost:3000/login \
  -d '{"user":"test","pass":"test123"}' \
  -H "Content-Type: application/json" \
  | grep -q "token"

# Exit 0 if token found (good), 1 if not (bad)

When Git Bisect Saves Your Bacon

The Regression Nobody Noticed: A client reported that exports stopped working... three weeks ago. 300+ commits. Git bisect found it in 9 checks. Turned out someone changed a date format in a utility function.

The Performance Degradation: API response times slowly crept from 100ms to 2 seconds over two months. Bisected with a performance test script. Found the commit that added an N+1 query.

The Flaky Test: A test passed 90% of the time. Used git bisect run with a script that ran the test 10 times. Found the commit that introduced a race condition.

The Gotchas (Because Nothing's Perfect)

Merge Commits Are Messy

If your history is full of merge commits, bisect can get confused. The bug might be in the merge itself, not in either branch. Sometimes you need to bisect with --first-parent to follow only the main branch:

git bisect start --first-parent

The Bug Might Be Environmental

If the bug only appears with specific data, configurations, or moon phases, bisect won't help much. You need reproducible conditions.

Multiple Bugs Can Confuse Things

If two different bugs were introduced at different times, you might find the wrong one. Be specific about what you're testing.

The Wisdom: Why This Matters

Here's the thing about debugging: time is your enemy. The longer you spend hunting bugs, the less time you have for building features, the more frustrated you get, and the more likely you are to make mistakes.

Git bisect transforms debugging from an art into a science. It's not about being clever or having deep knowledge of the codebase. It's about being systematic.

And there's something deeply satisfying about it. You're not randomly flailing. You're methodically narrowing down possibilities. Each test eliminates half the remaining suspects. You will find the bug. It's just math.

Your Action Plan

Next time you face a regression:

  1. Don't panic-check random commits. That's the old way.

  2. Identify a known-good commit. A tag, a release, last Friday—whatever you know worked.

  3. Start bisecting:

    git bisect start
    git bisect bad
    git bisect good <known-good-commit>
    
  4. Test systematically. Don't skip steps. Don't assume.

  5. Automate if possible. Write that test script. Let the computer do the work.

  6. Document what you find. Future you will appreciate it.

The Final Word

Git bisect won't make you a better programmer. It won't prevent bugs. It won't make Dave stop pushing "quick fixes" at 4:45 PM on Friday.

But it will make you a faster debugger. A more systematic investigator. A developer who can confidently say, "I'll have this fixed in 20 minutes," instead of "Uh... I'll need to investigate and get back to you."

And the next time someone breaks production, you won't panic. You'll smile slightly, crack your knuckles, and type git bisect start.

Because you're not just a developer anymore.

You're a detective. 🕵️


Now go forth and bisect. Your future debugging self will thank you. And maybe buy you a coffee. You'll have time for it while git does the work.