Git Bisect
Git bisect usa búsqueda binaria para encontrar el commit que introdujo un bug. Es muy eficiente, prueba log₂(n) commits en lugar de n.
Flujo básico de bisect
# Start bisect
git bisect start
# Mark current (buggy) commit as bad
git bisect bad
# Mark a known good commit
git bisect good v1.0.0
# Or: git bisect good abc1234
# Git checks out middle commit
# Test the code, then mark:
git bisect good # If bug not present
git bisect bad # If bug is present
# Repeat until found
# Bisecting: 3 revisions left to test
# [abc1234] First bad commit
# End bisect
git bisect reset
Bisect con rango de commits
# Start with known range
git bisect start HEAD v1.0.0
# Or specify bad and good in start
git bisect start bad-commit good-commit
# View current bisect state
git bisect log
Bisect automatizado
# Run a script to test each commit
git bisect start HEAD v1.0.0
git bisect run npm test
# Script should exit:
# 0 = good (test passes)
# 1-124, 126-127 = bad (test fails)
# 125 = skip (can't test this commit)
# Custom test script
git bisect run ./test-for-bug.sh
Ejemplo de script de test
#!/bin/bash
# test-for-bug.sh
# Build the project
npm run build || exit 125 # Skip if build fails
# Run specific test
npm test -- --grep "login feature" || exit 1
# Or check for specific behavior
if grep -r "buggy_pattern" src/; then
exit 1 # Bad
fi
exit 0 # Good
Saltar commits
# Skip current commit (can't test)
git bisect skip
# Skip a range
git bisect skip v1.0..v1.1
# Skip commits matching pattern
git bisect skip $(git rev-list --grep="WIP" HEAD)
Bisect con términos personalizados
# Use custom terms instead of good/bad
git bisect start --term-new=fixed --term-old=broken
# Mark commits with custom terms
git bisect fixed
git bisect broken
# Useful for finding fix instead of bug:
git bisect start --term-new=fixed --term-old=unfixed
Ver progreso de bisect
# Show bisect log
git bisect log
# Save log for replay
git bisect log > bisect.log
# Replay bisect session
git bisect replay bisect.log
# Visualize bisect
git bisect visualize
# Or: gitk (GUI)
Bisect con rutas
# Only bisect commits touching specific paths
git bisect start -- src/auth/
# Limit to specific file
git bisect start -- src/components/Login.jsx
Ejemplo complejo de bisect
# Find when performance degraded
git bisect start HEAD v1.0.0
# Test script for performance
cat > perf-test.sh << 'EOF'
#!/bin/bash
npm run build 2>/dev/null || exit 125
# Run benchmark
result=$(npm run benchmark --silent | grep "ops/sec" | awk '{print $1}')
# Bad if performance below threshold
if (( $(echo "$result < 1000" | bc -l) )); then
exit 1
fi
exit 0
EOF
chmod +x perf-test.sh
git bisect run ./perf-test.sh
Bisect para regresiones
# Find when feature stopped working
git bisect start
# Current: feature broken
git bisect bad HEAD
# Last known working
git bisect good v2.0.0
# Automated test
git bisect run sh -c '
npm install --silent 2>/dev/null
npm run build --silent 2>/dev/null || exit 125
npm test -- --grep "specific feature" --silent
'
Después de encontrar el bug
# Bisect found: abc1234 is first bad commit
# View the problematic commit
git show abc1234
# See what changed
git diff abc1234^..abc1234
# View blame for specific file
git blame -L 10,20 src/file.js abc1234
# End bisect and return to branch
git bisect reset
# Create fix
git checkout -b fix-regression
# Make changes...
git commit -m "Fix regression introduced in abc1234"
Consejos para un bisect efectivo
- Ten un test automatizado confiable
- Usa
skippara commits rotos/no testeables - Reduce con limitación por rutas
- Guarda logs de bisect para documentación
- Considera bisect run para tests complejos
- Recuerda ejecutar
bisect resetal terminar
Eficiencia
# Commits to test with bisect:
100 commits → ~7 tests (log₂100)
1000 commits → ~10 tests
10000 commits → ~14 tests
# Much faster than linear search!