{"record":{"id":"45a10bf32453f17f","repo":"gitbutlerapp/gitbutler","slug":"cannot-cherry-pick-above-a-reference","errorCode":null,"errorMessage":"Cannot cherry-pick above a reference","messagePattern":"Cannot cherry-pick above a reference","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/commit/cherry_pick.rs","lineNumber":40,"sourceCode":"pub fn cherry_pick_commits<'ws, 'meta, M: RefMetadata>(\n    mut editor: Editor<'ws, 'meta, M>,\n    source_commits: impl IntoIterator<Item = gix::ObjectId>,\n    relative_to: RelativeTo,\n    side: InsertSide,\n) -> anyhow::Result<(SuccessfulRebase<'ws, 'meta, M>, Vec<Selector>)> {\n    let mut seen = HashSet::new();\n    let sources = source_commits\n        .into_iter()\n        .filter(|id| seen.insert(*id))\n        .collect::<Vec<_>>();\n    if sources.is_empty() {\n        bail!(\"No commits were provided to cherry-pick\")\n    }\n    if matches!(\n        (&relative_to, side),\n        (RelativeTo::Reference(_), InsertSide::Above)\n    ) {\n        bail!(\"Cannot cherry-pick above a reference\")\n    }\n\n    let target = relative_to.to_selector(&editor)?;\n\n    let mut inserted_selectors = Vec::with_capacity(sources.len());\n    let mut previous_selector = None;\n    for source in sources {\n        // Give the copy its own change ID, retaining all other metadata.\n        let mut template = editor.find_commit(source)?;\n        let mut headers = Headers::try_from_commit(&template.inner).unwrap_or_default();\n        headers.change_id = Headers::from_config(&editor.repo().config_snapshot()).change_id;\n        headers.set_in_commit(&mut template.inner);\n        let template_id = editor.new_commit(template, DateMode::CommitterUpdateAuthorKeep)?;\n\n        let (anchor, insert_side) = match previous_selector {\n            Some(selector) => (selector, InsertSide::Above),\n            None => (target, side),\n        };","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-workspace/src/commit/cherry_pick.rs#L22-L58","documentation":"cherry_pick_commits rejects the combination RelativeTo::Reference(_) with InsertSide::Above: inserting commits above a reference would require rewriting what the ref points at in a way the rebase editor model does not support for this operation. Inserting below a reference, or above/below a commit, is fine. The check runs before any selector resolution.","triggerScenarios":"Calling cherry_pick_commits(editor, ids, RelativeTo::Reference(r), InsertSide::Above) — any reference anchor with the Above side.","commonSituations":"UIs exposing 'insert above' generically for both commit and branch targets; parameter mapping bugs that reuse InsertSide::Above for a reference target.","solutions":["Use InsertSide::Below when the anchor is a reference, or anchor Above on a commit instead.","Disable the 'above' placement option in the UI when the drop target is a branch/reference.","Validate the (relative_to, side) pair before invoking the API."],"exampleFix":"// before\ncherry_pick_commits(editor, ids, RelativeTo::Reference(target_ref), InsertSide::Above)?;\n\n// after\ncherry_pick_commits(editor, ids, RelativeTo::Reference(target_ref), InsertSide::Below)?;","handlingStrategy":"validation","validationCode":"if matches!((&relative_to, side), (RelativeTo::Reference(_), InsertSide::Above)) {\n    // invalid combination: clamp to Below or reject before calling\n    return Err(anyhow!(\"cannot insert above a reference\"));\n}","typeGuard":"fn cherry_pick_args_valid(relative_to: &RelativeTo, side: InsertSide) -> bool {\n    !matches!((relative_to, side), (RelativeTo::Reference(_), InsertSide::Above))\n}","tryCatchPattern":null,"preventionTips":["Only offer 'above' placement when the anchor is a commit.","Validate the (anchor kind, side) pair at the UI/action layer.","Document that references accept Below only."],"tags":["gitbutler","cherry-pick","invalid-arguments","rust"],"backgroundTag":"invalid-argument-combination","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}