|$ curl https://forge-ai.dev/api/markdown?path=docs/git/bisect
$cat docs/git-bisect.md
updated Recently·20 min read·published

Git Bisect

GitIntermediate🎯Free Tools
Introduction

git bisect uses binary search through your commit history to find the exact commit that introduced a bug. Instead of manually checking commits one by one (O(n)), bisect checks them logarithmically (O(log n)) — finding the culprit in ~10 steps for 1000 commits.

Manual Bisect

Manual bisect requires you to test each commit and tell Git whether it's good or bad. Git then narrows down the range until it finds the first bad commit.

bisect.sh
Bash
1# Start bisect
2git bisect start
3
4# Mark current commit as bad (has the bug)
5git bisect bad
6
7# Mark a known good commit (before the bug)
8git bisect good abc1234
9
10# Git checks out a commit in the middle
11# Test your code, then mark it:
12git bisect good # if this commit works
13# OR
14git bisect bad # if this commit has the bug
15
16# Repeat until Git finds the culprit
17# Bisect will output:
18# abc1234 is the first bad commit
19# commit abc1234
20# Author: Someone
21# Date: Mon Jul 7 14:30:00 2026
22
23# When done, return to main
24git bisect reset
25
26# One-liner: bisect between good and bad commits
27git bisect start HEAD abc1234
28git bisect run npm test

info

Always mark git bisect good or git bisect bad accurately. One wrong mark can send the bisect down the wrong path. Test carefully at each step.
Automated Bisect (bisect run)

git bisect runautomates the entire process by running a script at each commit. The script's exit code determines good (0) or bad (non-zero). No manual intervention needed.

automated-bisect.sh
Bash
1# Automated bisect with a test script
2git bisect start HEAD v1.0.0
3git bisect run npm test
4
5# The script must exit:
6# 0 = good (test passes)
7# 1-124 = bad (test fails)
8# 125 = skip (can't test this commit)
9# 126-127 = abort bisect
10
11# Custom test script with multiple checks
12cat > bisect-test.sh << 'EOF'
13#!/bin/bash
14set -e
15
16# Try to build
17npm run build 2>/dev/null || exit 1
18
19# Run the specific test
20npm test -- --grep "user authentication" || exit 1
21
22# Check if a specific function exists
23if ! grep -q "validateInput" src/utils.ts; then
24 exit 1 # Bug: missing function
25fi
26
27exit 0
28EOF
29
30chmod +x bisect-test.sh
31git bisect start HEAD v1.0.0
32git bisect run ./bisect-test.sh
33
34# Skip untestable commits (e.g., can't compile)
35git bisect run sh -c "npm install && npm test" || git bisect skip

best practice

Make your bisect test script fast and deterministic. A 10-step bisect with a 30-second test script completes in 5 minutes. A 5-minute test script takes 50 minutes. Optimize the test before running bisect.
Real-World Examples
real-bisect.sh
Bash
1# Find which commit broke a specific API endpoint
2git bisect start HEAD v2.0.0
3git bisect run curl -sf http://localhost:3000/api/health || exit 1
4
5# Find which commit introduced a performance regression
6cat > perf-test.sh << 'EOF'
7#!/bin/bash
8npm run build
9node server.js &
10SERVER_PID=$!
11sleep 2
12
13# Measure response time
14TIME=$(curl -w "%{time_total}" -s http://localhost:3000/api/data)
15kill $SERVER_PID
16
17# Fail if response time > 500ms
18if (( $(echo "$TIME > 0.5" | bc -l) )); then
19 echo "Slow response: ${TIME}s"
20 exit 1
21fi
22exit 0
23EOF
24
25git bisect start HEAD v1.5.0
26git bisect run ./perf-test.sh
27
28# Find which commit broke TypeScript types
29git bisect run sh -c "npm install && npx tsc --noEmit"
30
31# Find which commit broke a snapshot test
32git bisect run npx jest --updateSnapshot
Visual Regression Bisect
visual-bisect.sh
Bash
1# Bisect visual changes using screenshots
2cat > visual-test.sh << 'EOF'
3#!/bin/bash
4npm run build && npm start &
5APP_PID=$!
6sleep 3
7
8# Take screenshot with Playwright
9npx playwright screenshot http://localhost:3000 current.png
10
11# Compare with reference using ImageMagick
12if compare -metric AE reference.png current.png diff.png 2>/dev/null; then
13 kill $APP_PID
14 exit 0 # Good — no visual difference
15else
16 kill $APP_PID
17 exit 1 # Bad — visual regression
18fi
19EOF
20
21git bisect start HEAD v1.0.0
22git bisect run ./visual-test.sh

info

For visual regression bisect, commit reference screenshots to the repo. This gives bisect a stable baseline to compare against at each step.
$Blueprint — Engineering Documentation·Section ID: GIT-BS-01·Revision: 1.0