{"record":{"id":"c23cb641dda2043c","repo":"GitoxideLabs/gitoxide","slug":"a-recorded-scope-commit-is-disconnected-from-the-r","errorCode":null,"errorMessage":"a recorded scope commit is disconnected from the rebase base","messagePattern":"a recorded scope commit is disconnected from the rebase base","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/todo.rs","lineNumber":817,"sourceCode":"            .iter()\n            .any(|reference| reference.editable && reference.name == *name)\n    {\n        anyhow::bail!(\"the recorded HEAD ref is not editable\");\n    }\n    for tip in &state.tips {\n        repo.find_commit(*tip).context(\"could not find a recorded rebase tip\")?;\n    }\n    for id in &state.scope {\n        let commit = repo\n            .find_commit(*id)\n            .context(\"could not find a recorded scope commit\")?;\n        let parent = commit\n            .parent_ids()\n            .next()\n            .map(gix::Id::detach)\n            .context(\"a recorded scope commit has no parent\")?;\n        if parent != state.base && !scope.contains(&parent) && !continuation_sources.contains(id) {\n            anyhow::bail!(\"a recorded scope commit is disconnected from the rebase base\");\n        }\n    }\n    if state.resolved.is_some_and(|id| !scope.contains(&id)) {\n        anyhow::bail!(\"the resolved conflict is outside the rebase scope\");\n    }\n    if !continuation_sources.is_subset(&scope) {\n        anyhow::bail!(\"a continuation source is outside the rebase scope\");\n    }\n    Ok(())\n}\n\npub(crate) fn parse(repo: &gix::Repository, edited: &[u8]) -> Result<Option<Parsed>> {\n    repo.head()?.id().context(\"rebase todos require a born HEAD\")?;\n    let input = std::str::from_utf8(edited).context(\"the rebase todo is not UTF-8\")?;\n    let Some(mut state) = parse_state(repo, input)? else {\n        return Ok(None);\n    };\n    let scope: HashSet<_> = state.scope.iter().copied().collect();","sourceCodeStart":799,"sourceCodeEnd":835,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/todo.rs#L799-L835","documentation":"Every commit in the recorded rebase scope must connect back to the rebase base: its first parent must be the base, another scope commit, or the commit itself must be a continuation source (a conflict resolution point). Otherwise the captured scope is disconnected from the history being rewritten, indicating corrupt or tampered state.","triggerScenarios":"validate_state walks each scope commit via `parent_ids().next()`; the bail fires when a scope commit's first parent is not `state.base`, not in `scope`, and the commit is not listed in `continuation_sources`. Happens with hand-edited state, merged-in unrelated commits, or state persisted before external history modification.","commonSituations":"Amending or rebasing history with plain git while a tix rebase state exists; copying state between repos where the DAG differs; incomplete state files after a crash.","solutions":["Remove the stale rebase state and restart the rebase","Re-record state so all scope commits are captured together with their connecting history","If the commit legitimately roots a new history, register it as a continuation-source in the state"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure each scope commit's first parent connects to base or scope,\n// or the commit is a continuation source\nfor id in &state.scope {\n    let parent = repo.find_commit(*id)?.parent_ids().next().unwrap();\n    assert!(parent == state.base || scope.contains(&parent)\n        || state.continuation_sources.contains(id));\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"disconnected from the rebase base\") => {\n        // state graph is stale: discard and restart the rebase\n    }\n    r => r?,\n}","preventionTips":["Never rewrite history with plain git while tix rebase state exists","Copy rebase state only between identical repository states","Register legitimate new roots as continuation-source entries"],"tags":["rebase","state-validation","commit-graph"],"backgroundTag":"invalid-state-transition","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}