git bisect performs a binary search through commit history to identify the exact commit that introduced a bug or regression — without it, tracking a bug to its source in a repository with hundreds of commits requires manually checking each one. Instead of checking out commits one by one, git bisect halves the search space with each test: given 1,000 commits between the last known good state and the current broken state, bisect finds the culprit in at most 10 steps (log₂ 1000 ≈ 10). The workflow starts with git bisect start, marking a known bad commit with git bisect bad and a known good commit with git bisect good <hash> — Git then checks out the midpoint commit and waits for you to test it. After testing each checkout, you tell Git the result with git bisect good or git bisect bad, and Git moves to the next midpoint until it isolates the first bad commit. git bisect run <script> automates the entire process by running a test script at each step — the script exits 0 for good, 1 for bad, and 125 to skip a commit that cannot be tested (for example, because it does not compile). In WordPress development, automated bisect is ideal for PHP unit tests that verify a specific function, WP-CLI commands that check a database value, or curl commands that test a REST API response. git bisect skip is used when the current checkout is in an unrelated broken state — Git excludes it and picks a nearby commit to test instead. git bisect log records the session so far and git bisect replay <log> replays a saved session — useful for documenting the investigation in a bug report. The git stash post shows how to save your working tree before starting a bisect session so local changes do not interfere with the tested commits. The pre-commit hooks post ensures regressions are caught before they enter history, reducing how often bisect is needed in the first place. Always run git bisect reset when finished — it restores the original HEAD so you are not left on a detached HEAD pointing to a historical commit.
Problem: Identifying which specific commit introduced a WordPress bug or performance regression among hundreds of commits in a repository requires checking each one manually without a systematic strategy — a process that takes hours for a deep commit history.
Solution: Use git bisect run with an automated test script — a PHP unit test, WP-CLI command, or curl assertion — to let Git perform a binary search through commit history and identify the exact commit that introduced the regression in O(log n) steps.
# Start a bisect session
git bisect start
# Mark current HEAD as broken
git bisect bad
# Mark the last known working release tag as good
git bisect good v2.4.0
# Git checks out the midpoint commit — test manually, then mark it:
# git bisect good (if it passes)
# git bisect bad (if it fails)
# git bisect skip (if this commit cannot be tested)
# --- Fully automated bisect with a test script ---
# test-bisect.sh: exit 0 = good, exit 1 = bad, exit 125 = untestable
cat > /tmp/test-bisect.sh << 'SCRIPT'
#!/bin/bash
# Rebuild assets if needed
[ -f package.json ] && npm run build --silent 2>/dev/null
# Run the specific PHPUnit test that covers the regression
./vendor/bin/phpunit --filter test_product_price_calculation tests/ --no-coverage --quiet 2>&1
STATUS=$?
# Exit 125 if dependencies are missing (commit can't be built)
[ ! -f vendor/autoload.php ] && exit 125
exit $STATUS
SCRIPT
chmod +x /tmp/test-bisect.sh
# Run automated bisect — Git tests each midpoint and marks it automatically
git bisect run /tmp/test-bisect.sh
# Output: "abc1234 is the first bad commit"
# Review the identified commit
git show abc1234
# Check which files it changed
git diff abc1234^ abc1234 -- "*.php"
# Always reset bisect state when done
git bisect reset
# Save the session log for a bug report
git bisect log > bisect-session.log
NOTE: The test script passed to git bisect run must be idempotent — it will be executed 10–15 times on different checkout states. Avoid scripts that modify the database, send emails, or have other side effects, as those changes persist across bisect checkouts and corrupt the test environment.