Git bisect finds bugs by binary search through history, but sometimes you need to reset or recover when bisect gets stuck or you find the wrong commit.

The Error

During bisect session:

bash
git bisect reset

You see:

bash
fatal: Could not parse object 'refs/bisect/bad'
fatal: bisect run failed: exit code 128

Or:

bash
git bisect start
bash
fatal: There is already a bisect session
fatal: You need to run git bisect reset first

Or:

bash
git bisect bad abc1234
bash
fatal: Some revisions not in the given bad-good range
fatal: bisect: bad revision

Or bisect stuck at wrong commit: ``bash git bisect good

bash
Bisecting: 0 revisions left to test after this (roughly 0 steps)
abc1234 is the first bad commit

But the bug exists before this commit.

Why Bisect Reset Fails

Common causes:

  • Corrupt bisect refs - refs/bisect/* damaged or missing
  • Missing commits - Commit specified was deleted or lost
  • Stuck bisect state - Previous session not properly cleaned
  • Wrong good/bad boundaries - Bad commit is ancestor of good
  • Detached HEAD issues - Bisect leaves HEAD detached
  • Uncommitted changes - Dirty worktree during bisect

Diagnosis Steps

Check bisect status: ``bash git bisect log

Shows bisect history: `` git bisect start git bisect bad abc1234 git bisect good def5678 # Status: bisecting, 4 revisions to test

Check bisect refs: ``bash git for-each-ref refs/bisect/ ls .git/refs/bisect/

Check HEAD state: ``bash git status cat .git/HEAD

Check for bisect files: ``bash ls .git/BISECT_* 2>/dev/null

Files like BISECT_LOG, BISECT_NAMES, BISECT_START.

Verify commit exists: ``bash git cat-file -t abc1234

Solution 1: Force Reset Bisect

Standard reset fails, force cleanup:

bash
git bisect reset --force

Or manually: ```bash # Remove bisect refs git for-each-ref --format='%(refname)' refs/bisect/ | while read ref; do git update-ref -d "$ref" done

# Remove bisect files rm -f .git/BISECT_LOG .git/BISECT_NAMES .git/BISECT_START .git/BISECT_TERMS

# Return to original branch git checkout main # or your branch ```

Solution 2: Reset to Specific Branch

Reset and checkout specific branch:

bash
git bisect reset main

Or: ``bash git bisect reset HEAD~5

Returns to specified commit after bisect.

Solution 3: Fix Missing Bisect Refs

If refs/bisect/bad or refs/bisect/good missing:

bash
ls .git/refs/bisect/

Check bisect log for references: ``bash cat .git/BISECT_LOG

Manually recreate refs: ``bash # Find from log git update-ref refs/bisect/bad abc1234 git update-ref refs/bisect/good def5678

Then reset: ``bash git bisect reset

Solution 4: Abort Bisect with Dirty Worktree

Uncommitted changes block bisect:

bash
git bisect reset
bash
error: Your local changes would be overwritten by checkout

Stash changes: ``bash git stash push -m "bisect work" git bisect reset git stash pop

Or force reset: ``bash git checkout -- . git bisect reset

Solution 5: Fix Wrong Bisect Result

Bisect identifies wrong commit:

bash
git bisect good
bash
abc1234 is the first bad commit

But bug exists in earlier commits.

Continue bisect to find earlier: ``bash git bisect reset git bisect start git bisect bad <earlier-bad-commit> git bisect good <good-commit>

Or mark as skip: ``bash git bisect skip abc1234

Skip commits that are hard to test.

Solution 6: Recover After Accidental Reset

Reset before marking the culprit:

bash
git bisect reset

Oops! You didn't note the bad commit.

Check bisect log: ``bash cat .git/BISECT_LOG

Still contains history.

Check reflog: ``bash git reflog

Look for bisect entries.

Restart bisect with known range: ``bash git bisect start git bisect bad <last-known-bad> git bisect good <last-known-good>

Solution 7: Fix Bisect Terms

Using custom bisect terms:

bash
git bisect start --term-old fixed --term-new broken
git bisect broken
git bisect fixed

Reset with terms: ``bash git bisect reset --term-old fixed --term-new broken

Or just: ``bash git bisect reset

Terms reset automatically.

Solution 8: Handle Bisect with Run Script

Automated bisect gets stuck:

bash
git bisect run ./test-script.sh

Script returns unexpected codes.

Check script requirements: ``bash # Script should return: # 0 - if good (old term) # 1-127 (except 125) - if bad (new term) # 125 - if skip (cannot test)

Reset after failed run: ``bash git bisect reset

Fix script and restart: ``bash git bisect start git bisect bad bad-commit git bisect good good-commit git bisect run ./fixed-test-script.sh

Solution 9: Complete Manual Reset

When all else fails:

```bash # Full cleanup rm -rf .git/refs/bisect/ rm -f .git/BISECT_LOG .git/BISECT_NAMES .git/BISECT_START .git/BISECT_TERMS

# Return to known state git checkout main

# Verify cleanup git bisect log # Should fail: "We are not bisecting" git status # Should show clean state ```

Verification

Verify bisect ended: ``bash git bisect log

Should return: `` We are not bisecting.

Verify on proper branch: ``bash git status

Should show: `` On branch main nothing to commit, working tree clean

Verify no bisect refs remain: ``bash git for-each-ref refs/bisect/

Should return nothing.

Verify HEAD: ``bash cat .git/HEAD

Should show ref: refs/heads/main not bisect ref.

Bisect Commands Reference

```bash # Start bisect git bisect start [<bad> [<good>...]]

# Mark commits git bisect bad [<rev>] git bisect good [<rev>] git bisect skip [<rev>...] # Skip hard-to-test commits

# View status git bisect log git bisect visualize git bisect view

# Automated bisect git bisect run <script>

# Reset bisect git bisect reset [<branch>]

# Custom terms git bisect start --term-old=<term> --term-new=<term> ```

Best Practices

Note the bad commit before resetting: ``bash # When bisect finds culprit git bisect log | tail -5 # Note the commit git show abc1234 # Examine the commit # Then reset git bisect reset

Use bisect log for documentation: ``bash git bisect log > bisect-history.txt

Save bisect history for reference.

Skip untestable commits: ``bash git bisect skip

Don't force testing broken builds.

Test before marking: ``bash # Test current commit ./run-tests.sh # Based on result git bisect good # or bad

Start with tight range: ``bash git bisect start v2.0 v1.5

Narrow range speeds bisect.

Common Scenarios

Scenario: Bisect for regression in CI

```bash git bisect start git bisect bad HEAD # Current broken git bisect good v1.0 # Last known good

# Automated testing git bisect run "npm test && echo good || echo bad" ```

Scenario: Find where feature was added

bash
git bisect start --term-old without --term-new with
git bisect with HEAD
git bisect without v1.0
# Check each commit for feature presence

Scenario: Bisect takes too long

bash
# Skip builds that can't compile
git bisect skip
# Or narrow the range
git bisect reset
git bisect start bad~100 good~50

Bisect State Files

text
.git/
├── BISECT_LOG      # Bisect operation log
├── BISECT_NAMES    # Good/bad commit names
├── BISECT_START    # Original HEAD before bisect
├── BISECT_TERMS    # Custom terms if used
└── refs/
    └── bisect/
        ├── bad     # Current bad boundary
        ├── good    # Current good boundary
        └── good-*  # All good refs

Understanding these helps with manual recovery.