Skip to content
Back to skills

2502 Git Bisect Guide 24b6e3a4

BSecurity

Git bisect is a powerful binary search tool for finding the commit that introduced a bug or regression. It efficiently narrows down the problematic commit by testing commits in a logarithmic manner.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
testinggoc++bashdockertestingdebuggingrefactoringgitperformancedocumentation

Works with

  • terminal

Security analysis

B89/100
  • highPerforms destructive filesystem operations
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2502-git_bisect_guide_24b6e3a4 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2502 Git Bisect Guide 24b6e3a4?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2502 Git Bisect Guide 24b6e3a4
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2502-git-bisect-guide-24b6e3a4/badge)](https://www.skillsdirectory.com/skills/tools-only-2502-git-bisect-guide-24b6e3a4)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Git Bisect Guide

## Overview

Git bisect is a powerful binary search tool for finding the commit that introduced a bug or regression. It efficiently narrows down the problematic commit by testing commits in a logarithmic manner.

## How Git Bisect Works

### Binary Search Algorithm

Given a range of commits between a known "good" state and a known "bad" state, git bisect uses binary search to find the first bad commit:

```
Total commits: 100
Bisect steps: log₂(100) ≈ 7 tests
```

### Example Timeline

```
v1.0 (good) ─── commit A ─── commit B ─── commit C ─── HEAD (bad)
                    ↓           ↓           ↓
                  Test 1      Test 2      Test 3
                  (good)      (bad)    (not needed)
                              ↑
                        First bad commit!
```

## Basic Workflow

### Manual Bisect

```bash
# Start bisect session
git bisect start

# Mark current commit as bad
git bisect bad

# Mark a known good commit
git bisect good v1.0

# Git checks out a commit in the middle
# Test the commit manually
./run_tests.sh

# Mark the result
git bisect good   # if test passes
# OR
git bisect bad    # if test fails

# Repeat until git identifies the first bad commit

# End bisect session
git bisect reset
```

### Automated Bisect

```bash
# Start and mark good/bad commits
git bisect start HEAD v1.0

# Run automated bisect with test script
git bisect run ./bisect_test.sh

# Git will automatically test commits and find the culprit

# Review the results
git bisect log

# Reset to original state
git bisect reset
```

## Exit Codes for Automated Bisect

Git bisect interprets exit codes from test scripts:

| Exit Code | Meaning | Action |
|-----------|---------|--------|
| 0 | Good commit | Mark as good, continue bisecting |
| 1-124, 126-127 | Bad commit | Mark as bad, continue bisecting |
| 125 | Skip commit | Cannot test, skip this commit |
| 128+ | Fatal error | Abort bisect |

### Why Exit Code 125?

Exit code 125 is special - it tells git bisect to skip a commit that cannot be tested:

**Common skip scenarios**:
- Build fails
- Missing dependencies
- Incomplete feature (WIP commits)
- Test infrastructure not yet available
- Known broken commits

**Example**:
```bash
#!/bin/bash
# Skip commits that don't build
if ! make build; then
    exit 125  # Skip this commit
fi

# Run test
./run_test
```

## Advanced Techniques

### Bisect with Specific File Paths

Limit bisect to commits that touched specific files:

```bash
git bisect start -- path/to/file.py
git bisect bad HEAD
git bisect good v1.0
git bisect run ./test.sh
```

### Bisect with Date Range

```bash
# Find regression introduced after a specific date
git bisect start HEAD "$(git rev-list -1 --before='2024-01-01' HEAD)"
```

### Bisect with Commit Range

```bash
# Bisect between two specific commits
git bisect start <bad-commit> <good-commit>
```

### Skip Multiple Commits

```bash
# Skip a range of commits (e.g., known refactoring)
git bisect skip v1.1..v1.2

# Skip commits matching a pattern
git bisect skip $(git rev-list --grep="refactor" HEAD~50..HEAD)
```

### Bisect with Terms

Use custom terms instead of "good" and "bad":

```bash
# Use "old" and "new" for non-bug scenarios
git bisect start --term-old=old --term-new=new
git bisect new HEAD
git bisect old v1.0

# Or use "fast" and "slow" for performance
git bisect start --term-old=fast --term-new=slow
```

## Bisect Log and Replay

### Save Bisect Session

```bash
# Save bisect log
git bisect log > bisect_session.txt

# Reset bisect
git bisect reset

# Replay bisect session later
git bisect replay bisect_session.txt
```

### Bisect Log Format

```
# bad: [abc123] Commit message
# good: [def456] Commit message
git bisect start 'abc123' 'def456'
git bisect good xyz789
git bisect bad uvw012
```

## Visualizing Bisect Progress

### View Bisect State

```bash
# Show current bisect state
git bisect visualize

# Or with gitk
git bisect visualize --oneline --graph

# Show remaining commits to test
git bisect visualize --oneline | wc -l
```

### Bisect Log Analysis

```bash
# View full bisect log
git bisect log

# Count steps taken
git bisect log | grep -c "^git bisect"

# See which commits were tested
git bisect log | grep "^# "
```

## Common Patterns

### Pattern 1: Test Failure Bisect

```bash
#!/bin/bash
# Find commit that broke a specific test

pytest tests/test_feature.py::test_specific_case
exit $?
```

### Pattern 2: Performance Regression Bisect

```bash
#!/bin/bash
# Find commit that caused performance regression

THRESHOLD=1000  # milliseconds
DURATION=$(./benchmark | grep "Duration:" | awk '{print $2}')

if [ $DURATION -lt $THRESHOLD ]; then
    exit 0  # Good performance
else
    exit 1  # Performance regression
fi
```

### Pattern 3: Output Change Bisect

```bash
#!/bin/bash
# Find commit that changed program output

EXPECTED="Expected output"
ACTUAL=$(./program 2>&1)

if [ "$ACTUAL" = "$EXPECTED" ]; then
    exit 0  # Good
else
    exit 1  # Bad
fi
```

### Pattern 4: Build Failure Bisect

```bash
#!/bin/bash
# Find commit that broke the build

if make clean && make all; then
    exit 0  # Build succeeds
else
    exit 1  # Build fails
fi
```

## Troubleshooting

### Problem: Bisect Identifies Wrong Commit

**Causes**:
- Flaky tests (non-deterministic behavior)
- Incorrect exit codes in test script
- External dependencies changed
- Test environment not isolated

**Solutions**:
```bash
# Add retry logic
for i in {1..3}; do
    if ./test.sh; then
        ((PASS++))
    fi
done
[ $PASS -eq 3 ] && exit 0 || exit 1

# Fix random seeds
export RANDOM_SEED=42
export TZ=UTC

# Clean state
rm -rf /tmp/cache
```

### Problem: Too Many Commits Skipped

**Causes**:
- Build system changed during history
- Dependencies not available in older commits
- Test infrastructure added later

**Solutions**:
```bash
# Be more lenient with skipping
if ! make build 2>/dev/null; then
    exit 125  # Skip instead of failing
fi

# Install missing dependencies
if [ -f requirements.txt ]; then
    pip install -q -r requirements.txt || exit 125
fi
```

### Problem: Bisect Takes Too Long

**Causes**:
- Slow test execution
- Large commit range
- Many commits to test

**Solutions**:
```bash
# Add timeout
timeout 10s ./test.sh || exit 125

# Optimize test
# - Run only relevant tests
# - Use parallel execution
# - Cache build artifacts

# Narrow the range
git bisect start HEAD v1.5  # Instead of v1.0
```

### Problem: Cannot Reproduce Issue

**Causes**:
- Environment differences
- Missing configuration
- External dependencies

**Solutions**:
```bash
# Document environment
echo "Testing environment:" > bisect_env.txt
env >> bisect_env.txt
git --version >> bisect_env.txt

# Use containers for consistency
docker run --rm -v $(pwd):/code test-image ./bisect_test.sh
```

## Best Practices

1. **Test the test script first**: Verify it works on known good and bad commits
   ```bash
   git checkout <good-commit>
   ./bisect_test.sh  # Should exit 0

   git checkout <bad-commit>
   ./bisect_test.sh  # Should exit 1
   ```

2. **Make tests deterministic**: Fix random seeds, timestamps, and external state

3. **Keep tests fast**: Bisect runs O(log n) tests, but slow tests still add up

4. **Use exit code 125 liberally**: Skip untestable commits rather than marking them bad

5. **Log everything**: Save detailed logs for each tested commit

6. **Clean state between tests**: Remove caches, temporary files, and build artifacts

7. **Handle timeouts**: Prevent hanging tests from blocking bisect

8. **Document the process**: Save bisect logs and test scripts for future reference

## Performance Optimization

### Parallel Bisect

For independent test suites, run multiple bisects in parallel:

```bash
# Terminal 1: Bisect unit tests
git bisect start HEAD v1.0
git bisect run pytest tests/unit/

# Terminal 2: Bisect integration tests
git bisect start HEAD v1.0
git bisect run pytest tests/integration/
```

### Incremental Builds

Cache build artifacts to speed up compilation:

```bash
#!/bin/bash
# Use ccache for C/C++ builds
export CCACHE_DIR=/tmp/bisect_ccache
make CC="ccache gcc"
```

### Shallow Bisect

For very large repositories, use shallow clones:

```bash
git clone --depth 100 <repo-url>
git bisect start HEAD HEAD~50
```

## References

- Git bisect documentation: https://git-scm.com/docs/git-bisect
- Pro Git book chapter: https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git
- Git bisect examples: https://github.com/git/git/tree/master/contrib/examples

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.