jdx/mise · error
cannot merge dotfile Git history: {}
Error message
cannot merge dotfile Git history: {} What it means
Raised when the git call used to merge dotfile histories (e.g. `git merge-tree`/name-status plumbing with `-z`) fails with a status that is neither success nor the tolerated exit code 1. The tool cannot compute the merged view of the two histories, so it aborts and includes git's trimmed stderr. Exit code 1 is deliberately allowed because some plumbing calls use it to mean 'differences/conflicts reported' rather than failure.
Source
Thrown at src/system/history/shadow.rs:1289
}
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,
remote,
]))?;
if !output.status.success() && output.status.code() != Some(1) {
bail!(
"cannot merge dotfile Git history: {}",
String::from_utf8_lossy(&output.stderr).trim()
);
}
let text = String::from_utf8(output.stdout)?;
let mut fields = text.split('\0');
let tree = fields
.next()
.filter(|tree| !tree.is_empty())
.ok_or_else(|| eyre::eyre!("Git did not return a merged tree"))?
.to_owned();
let conflicts = fields
.filter(|path| !path.is_empty())
.map(str::to_owned)
.collect();
Ok((tree, conflicts))
}
View on GitHub (pinned to afd2eddd3a)
Solutions
- Reproduce the merge command manually in the shadow repo and read the stderr included in the error message.
- Run `git fsck --full` to detect and repair missing/corrupt objects.
- If history is unrecoverable, reset the shadow history and re-sync: push/pull the dotfiles afresh to rebuild both sides.
- Ensure no other process (backup/AV) is mutating the shadow repo's .git directory concurrently.
Defensive patterns
Strategy: fallback
Validate before calling
if !git_available() { eprintln!("git broken; history merge cannot run"); }
if !shadow_repo_healthy() { run_git_fsck(shadow_repo)?; } Try / catch
match history.merge(local, remote) {
Ok(merged) => apply(merged),
Err(e) if e.to_string().contains("cannot merge dotfile Git history") => {
repair_or_reset_shadow_repo()?;
}
Err(e) => return Err(e),
} Prevention
- Avoid partial backups/restores of the shadow repo's .git directory
- Exclude the shadow repo from aggressive cleanup tools and AV scanners
- Run `git fsck` periodically on the dotfile shadow repo
When it happens
Trigger: Invoking history merge for dotfiles when the underlying plumbing command exits with an unexpected code (not 0 and not 1): missing object, corrupt repo, invalid ref names, or git binary malfunction.
Common situations: Merging dotfile history after a machine was restored from a partial backup (missing git objects); a shadow repo truncated by disk-full conditions; refs renamed outside of mise while a sync is in flight.
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 determine dotfile Git ancestry: {}
- 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/36fb451065e0de2a.
Report an issue: GitHub.