How to fix Some good revs are not ancestors of the bad rev in Git

GitINTERMEDIATEMEDIUMUpdated Dec 6, 2025ยท 141 views

This error occurs when Git bisect detects that the commit marked as 'good' is not an ancestor of the 'bad' commit. This typically happens when searching for a fix instead of a regression, or when good/bad commits are swapped.

Quick fix

Fixes Some good revs are not ancestors of the bad rev

git merge-base --is-ancestor <good-commit> <bad-commit>
echo $?
  1. Verify the commit order
  2. Reset and swap good/bad if reversed
  3. Use old/new terminology for finding fixes
  4. Handle non-linear history with first-parent
git โ€” error
git merge-base --is-ancestor <good-commit> <bad-commit>
echo $?
Some good revs are not ancestors of the bad rev

What this error means

Git bisect uses binary search to find the commit that introduced a bug. For this to work, it requires that the "good" commit (where the bug doesn't exist) must be an ancestor of the "bad" commit (where the bug exists). This reflects the assumption that a bug was introduced at some point and persisted in all subsequent commits. Git's history is stored as a Directed Acyclic Graph (DAG), where each commit points to its parent(s). When you mark a commit as "good" and another as "bad," Git expects to traverse from the bad commit backward through the history to reach the good commit. If the good commit is not reachable by following parent pointers from the bad commit, Git cannot perform the binary search. This error commonly appears in three scenarios: you've accidentally swapped which commit is good vs bad, you're trying to find when a bug was *fixed* rather than introduced (reverse bisect), or you're working with a complex non-linear history where branches were merged in unexpected ways.

Typical symptoms

  • Git bisect fails immediately after marking commits as good and bad
  • Error message: 'Some good revs are not ancestors of the bad rev'
  • Additional message: 'git bisect cannot work properly in this case'
  • Git suggests: 'Maybe you mistook good and bad revs?'
  • Bisect session refuses to continue despite valid commits being specified

Common causes

  1. Good and bad commits are swapped - the 'bad' commit is actually older than the 'good' commit (most common)
  2. Attempting to find a fix commit instead of a regression - the bug exists in older commits but is fixed in newer ones
  3. Working on a feature branch that was rebased, causing historical commits to be unreachable from the current HEAD
  4. Complex merge history where the 'good' commit is on a parallel branch that was never merged into the path to 'bad'
  5. Using the wrong branch or commit reference, pointing to unrelated parts of the repository history
  6. Cherry-picked commits that exist in multiple places in the DAG with different ancestry relationships

How to fix "Some good revs are not ancestors of the bad rev"

1Verify the commit order

First, confirm which commit is actually older. Check if the "good" commit is an ancestor of the "bad" commit:

bash
git merge-base --is-ancestor <good-commit> <bad-commit>
echo $?

If this returns 0, the good commit IS an ancestor of bad (correct order). If it returns 1, the commits are in the wrong order or on different branches.

You can also visualize the relationship:

bash
git log --oneline --graph <good-commit>..<bad-commit>
2Reset and swap good/bad if reversed

If you simply have the commits backwards, reset the bisect and start over with them swapped:

bash
git bisect reset
git bisect start
git bisect bad <formerly-good-commit>
git bisect good <formerly-bad-commit>

Remember: "good" means "the bug is NOT present" and "bad" means "the bug IS present." The bug should exist in the bad commit but not in the good commit.

3Use old/new terminology for finding fixes

If you're trying to find which commit *fixed* a bug (rather than introduced one), the traditional good/bad terminology is confusing. Git provides alternative terms:

bash
git bisect reset
git bisect start --term-old=unfixed --term-new=fixed
git bisect unfixed <older-commit-with-bug>
git bisect fixed <newer-commit-without-bug>

Or use the built-in old/new terms (Git 2.7+):

bash
git bisect reset
git bisect start
git bisect old <commit-where-bug-exists>
git bisect new <commit-where-bug-is-fixed>

Note: You cannot mix good/bad with old/new in the same session.

4Handle non-linear history with first-parent

If you have a complex merge history and want to bisect only the mainline commits (skipping feature branch commits), use the --first-parent option (Git 2.29+):

bash
git bisect reset
git bisect start --first-parent
git bisect bad HEAD
git bisect good <known-good-commit>

This restricts bisect to follow only the first parent at each merge, typically the mainline branch.

5Find the correct ancestor with merge-base

If your good commit is on a different branch, find a common ancestor that both branches share:

bash
git merge-base <good-commit> <bad-commit>

Use this merge base as your starting point:

bash
git bisect reset
git bisect start
git bisect bad <bad-commit>
git bisect good $(git merge-base <good-commit> <bad-commit>)

This ensures the good commit is in the ancestry path of the bad commit.

6Visualize the history to understand the DAG

Before starting bisect, visualize the commit graph to understand the relationship between commits:

bash
git log --oneline --graph --all --decorate | head -50

Or for a specific range:

bash
git log --oneline --graph <good-commit>...<bad-commit>

The three-dot syntax shows commits reachable from either commit but not both, helping you see if they're on divergent branches.

7Use git bisect run with proper term handling

When automating bisect with a test script, ensure your script correctly handles the terminology you're using:

bash
# For finding a regression (traditional)
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
git bisect run ./test-script.sh

# For finding a fix (custom terms)
git bisect start --term-old=broken --term-new=fixed
git bisect broken v1.0.0
git bisect fixed HEAD
git bisect run ./test-script.sh

The test script should exit with code 0 for "good/old/fixed" and non-zero for "bad/new/broken".

Advanced notes

### Understanding Git's DAG Structure

Git stores commits as a Directed Acyclic Graph (DAG). Each commit points to its parent commit(s), creating a tree-like structure that flows backward in time. The "acyclic" property means you can never follow parent pointers and return to where you started.

When bisect runs, it needs to find a path from the bad commit to the good commit by following parent pointers. If no such path exists (the good commit is not an ancestor of bad), bisect cannot function because there's no linear sequence of commits to binary search through.

### Binary Search Requirements

Git bisect works by repeatedly halving the range of suspect commits. For this to work:
1. The good commit must be reachable from the bad commit
2. The bug must be consistently reproducible
3. The bug must have been introduced once and persisted (no intermittent fixes and re-introductions)

### Handling Evil Merges

"Evil merges" are merge commits where the resolution itself introduces a bug (not present in either parent). These are tricky because:
- The bug only appears after the merge
- Neither parent commit shows the bug

If bisect points to a merge commit, you may need to do a secondary bisect within the merged branch, or manually examine the merge diff:

bash
git show <merge-commit> --diff-filter=M

### Theoretical Limitations

Research has shown that git bisect's algorithm, while efficient for linear history, can require exponentially more queries than optimal in complex DAGs. For very tangled histories, consider:
- Rebasing to linearize history before bisecting
- Using --first-parent to simplify the search space
- Manual binary search on a specific branch

### Skip Problematic Commits

If some commits cannot be tested (e.g., they don't compile), use skip:

bash
git bisect skip
# Or skip a range
git bisect skip v2.0..v2.1

Skipping too many commits reduces bisect's effectiveness but is better than marking untestable commits incorrectly.

Frequently asked questions

What does "Some good revs are not ancestors of the bad rev" mean?
Git bisect uses binary search to find the commit that introduced a bug. For this to work, it requires that the "good" commit (where the bug doesn't exist) must be an ancestor of the "bad" commit (where the bug exists). This reflects the assumption that a bug was introduced at some point and persisted in all subsequent commits.
How do I fix "Some good revs are not ancestors of the bad rev"?
This error occurs when Git bisect detects that the commit marked as 'good' is not an ancestor of the 'bad' commit. This typically happens when searching for a fix instead of a regression, or when good/bad commits are swapped.
What causes "Some good revs are not ancestors of the bad rev"?
Good and bad commits are swapped - the 'bad' commit is actually older than the 'good' commit (most common) Attempting to find a fix commit instead of a regression - the bug exists in older commits but is fixed in newer ones Working on a feature branch that was rebased, causing historical commits to be unreachable from the current HEAD
Is the "Some good revs are not ancestors of the bad rev" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading