{"record":{"id":"05d79a73808c8870","repo":"jdx/mise","slug":"local-and-origin-histories-are-unrelated-use-a-fr","errorCode":null,"errorMessage":"local and origin histories are unrelated; use a fresh setup store to adopt origin, or reconcile the repositories explicitly with Git. Neither history was replaced","messagePattern":"local and origin histories are unrelated; use a fresh setup store to adopt origin, or reconcile the repositories explicitly with Git\\. Neither history was replaced","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/sync/graph.rs","lineNumber":31,"sourceCode":"    pub base: Option<String>,\n}\n\n#[derive(Debug)]\npub(crate) struct Candidate {\n    pub commit: String,\n    expected_local: Option<String>,\n    expected_remote: Option<String>,\n}\n\nimpl Heads {\n    pub(crate) fn read(repo: &HistoryRepo) -> Result<Self> {\n        let local = repo.ref_oid(HistoryRepo::HISTORY_REF)?;\n        let remote = repo.ref_oid(UPSTREAM_REF)?;\n        let base = match (&local, &remote) {\n            (Some(local), Some(remote)) => {\n                let bases = repo.merge_bases(local, remote)?;\n                if bases.is_empty() {\n                    bail!(\n                        \"local and origin histories are unrelated; use a fresh setup store to adopt origin, or reconcile the repositories explicitly with Git. Neither history was replaced\"\n                    );\n                }\n                // A criss-cross merge has shared ancestry but no unique base.\n                // It needs a merge commit, never an arbitrary fast-forward.\n                (bases.len() == 1).then(|| bases[0].clone())\n            }\n            _ => None,\n        };\n        Ok(Self {\n            local,\n            remote,\n            base,\n        })\n    }\n\n    /// Preparing a candidate does not advance a branch or write live files.\n    /// The caller must finish its complete application before adopting it.","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/sync/graph.rs#L13-L49","documentation":"When computing the sync base, read() finds both a local history ref and an origin ref but repo.merge_bases() returns no common ancestor — the two histories are unrelated. The sync deliberately aborts without replacing either history, because fast-forwarding or adopting origin would silently discard one lineage of saved files.","triggerScenarios":"Calling read() on a HistoryRepo where HISTORY_REF and UPSTREAM_REF both exist but share no merge base (disjoint commit graphs).","commonSituations":"A fresh origin store was force-pushed/re-created while the local machine kept its old history; two machines independently initialized setup stores and both were pushed; restoring origin from a new init instead of cloning.","solutions":["Force-adopt origin by initializing a fresh setup store from origin (discarding unrelated local history) if origin is authoritative.","Reconcile explicitly with git: graft or merge the two roots manually in the history repo, then push.","Back up saved files, delete the local history ref, and re-pull to start from origin."],"exampleFix":"# before: divergent unrelated histories\n$ mise bootstrap dotfiles sync   # fails\n# after: adopt origin with a fresh store\n$ rm -rf ~/.local/share/mise/history && mise bootstrap dotfiles pull","handlingStrategy":"fallback","validationCode":"let local = repo.ref_oid(HistoryRepo::HISTORY_REF)?;\nlet remote = repo.ref_oid(UPSTREAM_REF)?;\nif let (Some(l), Some(r)) = (&local, &remote) {\n    if repo.merge_bases(l, r)?.is_empty() {\n        eprintln!(\"histories unrelated; decide adopt-origin vs manual reconcile\");\n    }\n}","typeGuard":null,"tryCatchPattern":"match read(repo) {\n    Ok(base) => proceed(base),\n    Err(e) if e.to_string().contains(\"histories are unrelated\") => {\n        eprintln!(\"prompt: adopt origin (fresh store) or reconcile with git\");\n        prompt_unrelated_history_action()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always clone/adopt the origin store instead of re-initializing independently.","Avoid force-pushing or recreating the origin history store.","Back up saved dotfiles before any history surgery."],"tags":["git","history-divergence","sync"],"backgroundTag":"invalid-state-transition","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}