Find Bugs Fast with Git Bisect

December 17, 2024

Debugging can feel overwhelming, especially in large codebases with numerous commits. But what if there was a way to zero in on the exact commit where a bug was introduced? Enter Git Bisect, a powerful tool that uses binary search to pinpoint problematic commits.

In this post, we’ll break down how to use Git Bisect effectively and even automate the process for maximum efficiency. Let’s dive in!

category: web-development type: post


The Problem: A Buggy Calculator

To illustrate how Git Bisect works, let’s consider a simple command-line calculator. This calculator performs basic operations like addition, subtraction, multiplication, and division.

Here’s how it works:

  • divide 10 by 2 returns 5.
  • multiply 10 by 2 returns 20.

However, when adding numbers, the calculator produces incorrect results:

  • add 10 and 2 outputs 8 instead of 12.

With multiple files in the project and several commits in the Git history, manually hunting down the bug isn’t practical. So, let’s use Git Bisect!

category: web-development type: post


Step 1: Starting Git Bisect

To begin, initialize the Git Bisect session:

git bisect start

Git prompts you to mark a bad commit (where the bug exists) and a good commit (before the bug was introduced).

Since the current state of the code is broken, mark it as bad:

git bisect bad

If you know a commit where the calculator worked correctly, mark it as good:

git bisect good <commit-hash>

category: web-development type: post


Step 2: Let Git Bisect Narrow Down the Problem

Git Bisect will check out a commit halfway between the good and bad commits. At this point, test the calculator:

  • Run the addition operation (add 10 and 2).
  • If the bug persists, mark the commit as bad:
    git bisect bad
    
  • If it works correctly, mark it as good:
    git bisect good
    

Git continues this binary search, narrowing down the range of commits until it identifies the exact commit where the bug was introduced.

category: web-development type: post


Step 3: Ending the Bisect Session

Once the problematic commit is found, Git will display its hash:

<commit-hash> is the first bad commit

Inspect the commit to understand the issue. In our example, the addition logic mistakenly performs subtraction.

Finally, reset the bisect session to return to your original state:

git bisect reset

category: web-development type: post


Step 4: Automating the Process

Manually testing each commit can be tedious, especially in larger projects. Thankfully, Git allows you to automate testing with git bisect run.

Here’s how it works:

  1. Create a test script to verify the bug.
  2. Use git bisect run with the script to automate testing.

For example:

git bisect run npm test

Git will execute the test at each commit and determine whether it passes or fails based on the return code:

  • 0: No problem (good commit).
  • 1: Problem detected (bad commit).

category: web-development type: post


A Practical Example

Step 1: Adding a Test Script

Create a new test file (e.g., calculate.test.js) with the following code:

const calculate = require("./calculate");

test("should add two numbers correctly", () => {
  expect(calculate("add", 10, 20)).toBe(30);
});

Run the test to ensure it fails (indicating the bug exists):

npm test

Step 2: Automate the Bisect Process

Start Git Bisect and mark the commits:

git bisect start
git bisect bad
git bisect good <commit-hash>

Run the automated bisect command:

git bisect run npm test

Git will now run the test for each commit, narrowing down the range until it identifies the first bad commit.

category: web-development type: post


Bonus Tip: Reordering Commits

If your test script wasn’t present at earlier commits, you can reorder commits using interactive rebasing. This ensures the test runs at every step of the bisect process:

git rebase -i <commit-hash>

Move the test script commit to the beginning of the history, save the changes, and rerun Git Bisect with automation.

category: web-development type: post


Conclusion

Git Bisect is a game-changer for debugging, allowing you to efficiently locate the commit where a bug was introduced. Automating the process with git bisect run takes it to the next level, saving you time and effort.

Next time you face a bug in your codebase, let Git Bisect do the heavy lifting!