jdx/mise · error
cannot determine dotfile Git ancestry: {}
Error message
cannot determine dotfile Git ancestry: {} What it means
This fires when `git merge-base --all <local> <remote>` exits with a status other than the expected 0 (ancestors found) or 1 (no common ancestor). Since the command cannot determine whether the two dotfile history tips share ancestry, the operation aborts and surfaces git's stderr. It guards the merge/rebase logic that relies on knowing the common history.
Source
Thrown at src/system/history/shadow.rs:1267
/// Deletes a ref if it exists.
pub(crate) fn delete_ref(&self, name: &str) -> Result<()> {
if self.ref_oid(name)?.is_some() {
self.git
.run(PlumbingCall::new(["update-ref", "-d", name]))?;
}
Ok(())
}
/// Find all common ancestors without treating Git failures as absence.
pub(crate) fn merge_bases(&self, local: &str, remote: &str) -> Result<Vec<String>> {
let output =
self.git
.output_unchecked(PlumbingCall::new(["merge-base", "--all", local, remote]))?;
if output.status.code() == Some(1) {
return Ok(vec![]);
}
if !output.status.success() {
bail!(
"cannot determine dotfile Git ancestry: {}",
String::from_utf8_lossy(&output.stderr).trim()
);
}
let text = String::from_utf8(output.stdout)?;
Ok(text.lines().map(str::to_owned).collect())
}
/// Merge complete ordinary trees using Git's recursive merge-base handling.
/// Conflict trees are never adopted or written into live configuration.
pub(crate) fn merge_tree(&self, local: &str, remote: &str) -> Result<(String, Vec<String>)> {
let output = self.git.output_unchecked(PlumbingCall::new([
"merge-tree",
"--write-tree",
"--name-only",
"--no-messages",
"-z",
local,View on GitHub (pinned to afd2eddd3a)
Solutions
- Run `git merge-base --all <local> <remote>` inside the shadow repo yourself and read the stderr echoed in the error.
- Check that both refs/commits exist: `git rev-parse <local> <remote>`.
- If refs are dangling after a force-push or GC, re-sync the dotfile history (`mise dot` pull/push) to rebuild the shared base.
- As a last resort, `git fsck` the shadow repository and restore it from a fresh clone or backup.
Defensive patterns
Strategy: fallback
Validate before calling
for r in [&local, &remote] {
if !repo_rev_parse_ok(r) { eprintln!("ref {r} missing from shadow repo"); }
} Try / catch
match history.common_ancestors(local, remote) {
Ok(ans) => merge_with(ans),
Err(e) if e.to_string().contains("cannot determine dotfile Git ancestry") => {
eprintln!("shadow repo inconsistent; re-syncing history");
resync_history()?;
}
Err(e) => return Err(e),
} Prevention
- Don't manually reset or GC the dotfile shadow repo
- Run `git fsck` after machine restores or disk-full events
- Re-sync history after force-pushes instead of merging across rewrites
When it happens
Trigger: Calling the ancestry check when the `merge-base --all` plumbing call fails for reasons other than 'no common ancestor' — e.g. one of the refs does not exist, the repository is corrupt, or git itself is broken.
Common situations: A dotfile shadow repo whose branch was force-deleted or garbage-collected while a local ref still points at it; a hand-edited or corrupted .git directory; running with a broken or partial git installation.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- cannot merge dotfile Git history: {}
- comparing checkpoints requires git
- listing snapshot files requires git
- tracking declarations updated, but could not commit the chan
- failed to locate Git repository for {}: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/8c7d6ce31d533b74.
Report an issue: GitHub.