{"record":{"id":"36fb451065e0de2a","repo":"jdx/mise","slug":"cannot-merge-dotfile-git-history","errorCode":null,"errorMessage":"cannot merge dotfile Git history: {}","messagePattern":"cannot merge dotfile Git history: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/shadow.rs","lineNumber":1289,"sourceCode":"        }\n        let text = String::from_utf8(output.stdout)?;\n        Ok(text.lines().map(str::to_owned).collect())\n    }\n\n    /// Merge complete ordinary trees using Git's recursive merge-base handling.\n    /// Conflict trees are never adopted or written into live configuration.\n    pub(crate) fn merge_tree(&self, local: &str, remote: &str) -> Result<(String, Vec<String>)> {\n        let output = self.git.output_unchecked(PlumbingCall::new([\n            \"merge-tree\",\n            \"--write-tree\",\n            \"--name-only\",\n            \"--no-messages\",\n            \"-z\",\n            local,\n            remote,\n        ]))?;\n        if !output.status.success() && output.status.code() != Some(1) {\n            bail!(\n                \"cannot merge dotfile Git history: {}\",\n                String::from_utf8_lossy(&output.stderr).trim()\n            );\n        }\n        let text = String::from_utf8(output.stdout)?;\n        let mut fields = text.split('\\0');\n        let tree = fields\n            .next()\n            .filter(|tree| !tree.is_empty())\n            .ok_or_else(|| eyre::eyre!(\"Git did not return a merged tree\"))?\n            .to_owned();\n        let conflicts = fields\n            .filter(|path| !path.is_empty())\n            .map(str::to_owned)\n            .collect();\n        Ok((tree, conflicts))\n    }\n","sourceCodeStart":1271,"sourceCodeEnd":1307,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/shadow.rs#L1271-L1307","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"if !git_available() { eprintln!(\"git broken; history merge cannot run\"); }\nif !shadow_repo_healthy() { run_git_fsck(shadow_repo)?; }","typeGuard":null,"tryCatchPattern":"match history.merge(local, remote) {\n    Ok(merged) => apply(merged),\n    Err(e) if e.to_string().contains(\"cannot merge dotfile Git history\") => {\n        repair_or_reset_shadow_repo()?;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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"],"tags":["git","dotfiles","merge","plumbing"],"backgroundTag":"git-command-failed","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}