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
returns5
.multiply 10 by 2
returns20
.
However, when adding numbers, the calculator produces incorrect results:
add 10 and 2
outputs8
instead of12
.
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:
- Create a test script to verify the bug.
- 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!