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.
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.
First, confirm which commit is actually older. Check if the "good" commit is an ancestor of the "bad" commit:
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:
git log --oneline --graph <good-commit>..<bad-commit>If you simply have the commits backwards, reset the bisect and start over with them swapped:
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.
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:
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+):
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.
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+):
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.
If your good commit is on a different branch, find a common ancestor that both branches share:
git merge-base <good-commit> <bad-commit>Use this merge base as your starting point:
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.
Before starting bisect, visualize the commit graph to understand the relationship between commits:
git log --oneline --graph --all --decorate | head -50Or for a specific range:
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.
When automating bisect with a test script, ensure your script correctly handles the terminology you're using:
# 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.shThe test script should exit with code 0 for "good/old/fixed" and non-zero for "bad/new/broken".
### 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:
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:
git bisect skip
# Or skip a range
git bisect skip v2.0..v2.1Skipping too many commits reduces bisect's effectiveness but is better than marking untestable commits incorrectly.
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git