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
2
git bisect start
3
4
# Mark current commit as bad (has the bug)
5
git bisect bad
6
7
# Mark a known good commit (before the bug)
8
git bisect good abc1234
9
10
# Git checks out a commit in the middle
11
# Test your code, then mark it:
12
git bisect good # if this commit works
13
# OR
14
git 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
24
git bisect reset
25
26
# One-liner: bisect between good and bad commits
27
git bisect start HEAD abc1234
28
git 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
2
git bisect start HEAD v1.0.0
3
git 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
12
cat > bisect-test.sh << 'EOF'
13
#!/bin/bash
14
set -e
15
16
# Try to build
17
npm run build 2>/dev/null || exit 1
18
19
# Run the specific test
20
npm test -- --grep "user authentication" || exit 1
21
22
# Check if a specific function exists
23
if ! grep -q "validateInput" src/utils.ts; then
24
exit 1 # Bug: missing function
25
fi
26
27
exit 0
28
EOF
29
30
chmod +x bisect-test.sh
31
git bisect start HEAD v1.0.0
32
git bisect run ./bisect-test.sh
33
34
# Skip untestable commits (e.g., can't compile)
35
git 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
2
git bisect start HEAD v2.0.0
3
git bisect run curl -sf http://localhost:3000/api/health || exit 1
4
5
# Find which commit introduced a performance regression