{"record":{"id":"7e79364d77c7727b","repo":"GitoxideLabs/gitoxide","slug":"the-move-target-must-not-be-part-of-the-moved-stac","errorCode":null,"errorMessage":"the move target must not be part of the moved stack","messagePattern":"the move target must not be part of the moved stack","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/rebase.rs","lineNumber":676,"sourceCode":"\n    let mut stack = vec![head];\n    let mut stack_parent = HashMap::new();\n    loop {\n        let id = *stack.last().expect(\"a stack always contains HEAD\");\n        let parents = graph.parents_of(id).context(\"a moved stack commit is incomplete\")?;\n        let [parent] = parents.as_slice() else {\n            anyhow::bail!(\"moving a stack requires every commit to have exactly one parent\");\n        };\n        stack_parent.insert(id, *parent);\n        if id == base {\n            break;\n        }\n        stack.push(*parent);\n    }\n    stack.reverse();\n    let stack_set: HashSet<_> = stack.iter().copied().collect();\n    if stack_set.contains(&target) {\n        anyhow::bail!(\"the move target must not be part of the moved stack\");\n    }\n    let base_parent = stack_parent[&base];\n    if base_parent == target {\n        anyhow::bail!(\"the stack is already directly above the move target\");\n    }\n\n    let target_rewritten = graph.is_ancestor(base, target);\n    let mut scope = Vec::new();\n    let mut scope_set = HashSet::new();\n    for id in graph\n        .descendants_in_parent_order(base)\n        .context(\"the stack base is not in the loaded history\")?\n        .into_iter()\n        .chain(\n            graph\n                .descendants_in_parent_order(target)\n                .context(\"the move target is not in the loaded history\")?,\n        )","sourceCodeStart":658,"sourceCodeEnd":694,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/rebase.rs#L658-L694","documentation":"The move target is the commit the stack will be re-parented onto. If the target itself is inside the stack being moved (base..head), the move would be circular — a commit cannot be both moved and its own new parent — so the plan builder rejects it once the stack has been enumerated.","triggerScenarios":"Calling `move_insert_plan`/`stack_insert_plan(repo, graph, base, head, target)` where `target` equals any commit id in the base..head stack (including base or head).","commonSituations":"UI selection where the user picks a commit within the highlighted stack as the destination; scripts computing the target from the same range as the stack.","solutions":["Pick a target commit outside the base..head stack, e.g. a commit the stack currently does not contain.","Check membership before calling: ensure `target` is not among the commits from base to head.","If the intent is to reorder within the stack, use a reorder/edit operation rather than stack insert."],"exampleFix":"// before\nstack_insert_plan(&repo, &graph, base, head, some_commit_inside_stack)?\n\n// after\nanyhow::ensure!(!stack_ids(base, head).contains(&target), \"target must be outside the stack\");\nstack_insert_plan(&repo, &graph, base, head, target)?","handlingStrategy":"validation","validationCode":"// enumerate stack ids from base..head and reject overlap with target\nlet mut stack_ids = std::collections::HashSet::new();\nlet mut id = head;\nloop {\n    stack_ids.insert(id);\n    if id == base { break; }\n    id = graph.parents_of(id)?[0];\n}\nif stack_ids.contains(&target) {\n    eprintln!(\"target is inside the moved stack\");\n    return Ok(());\n}","typeGuard":"fn target_outside_stack(graph: &HistoryGraph, base: ObjectId, head: ObjectId, target: ObjectId) -> bool {\n    let mut id = head;\n    loop {\n        if id == target { return false; }\n        if id == base { return true; }\n        match graph.parents_of(id) { Ok(p) if !p.is_empty() => id = p[0], _ => return true }\n    }\n}","tryCatchPattern":"match stack_insert_plan(&repo, &graph, base, head, target) {\n    Err(e) if e.to_string().contains(\"part of the moved stack\") => eprintln!(\"pick a destination outside the stack\"),\n    other => other?,\n}","preventionTips":["Exclude stack members from destination pickers in UIs","Compute the stack range once and validate all three ids together","Treat base and head as implicitly invalid targets"],"tags":["git","rebase","circular-dependency","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}