{"record":{"id":"59691250e074260d","repo":"gitbutlerapp/gitbutler","slug":"cannot-squash-a-commit-into-itself","errorCode":null,"errorMessage":"Cannot squash a commit into itself","messagePattern":"Cannot squash a commit into itself","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/commit/squash_commits.rs","lineNumber":156,"sourceCode":"    editor: Editor<'ws, 'meta, M>,\n    subjects: Vec<S>,\n    target_commit: T,\n    how_to_combine_messages: MessageCombinationStrategy,\n) -> Result<SquashCommitsOutcome<'ws, 'meta, M>> {\n    let mut seen_subjects = std::collections::HashSet::with_capacity(subjects.len());\n\n    if subjects.is_empty() {\n        bail!(\"Need at least 2 commits to squash\")\n    }\n\n    let (target_commit_selector, target_commit_obj) =\n        editor.find_selectable_commit(target_commit)?;\n\n    let mut subject_selectors = Vec::with_capacity(subjects.len());\n    for subject_commit in subjects {\n        let (subject_commit_selector, _) = editor.find_selectable_commit(subject_commit)?;\n        if subject_commit_selector == target_commit_selector {\n            bail!(\"Cannot squash a commit into itself\")\n        }\n        if !seen_subjects.insert(subject_commit_selector) {\n            continue;\n        }\n        subject_selectors.push(subject_commit_selector);\n    }\n\n    let subject_commit_ids = subject_selectors\n        .iter()\n        .map(|commit_selector| {\n            let (_, commit) = editor.find_selectable_commit(*commit_selector)?;\n            Ok(commit.id)\n        })\n        .collect::<Result<Vec<_>>>()?;\n    let squashed_tree = editor.merge_commit_changes_to_tree(\n        target_commit_obj.id,\n        subject_commit_ids,\n        editor.repo().merge_options_force_ours()?,","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-workspace/src/commit/squash_commits.rs#L138-L174","documentation":"A subject commit resolved to the same selector as the target commit, meaning the caller asked to squash a commit into itself. The library rejects this because combining a commit with itself is a no-op/undefined operation.","triggerScenarios":"squash_commits is called where any entry in subjects resolves to the same commit selector as target_commit (e.g. the same commit ID passed in both roles).","commonSituations":"Scripts that build the subject list including the target commit; UI allowing the currently-selected commit to be both target and subject; duplicate ID handling gone wrong.","solutions":["Remove the target commit from the subjects list before calling","Pick a different target commit that is not among the subjects","Filter subjects: subjects.retain(|s| s != target) before invoking"],"exampleFix":"// before\neditor.squash_commits(target, vec![target, other], strategy)?; // target in subjects\n// after\nlet subjects: Vec<_> = vec![target, other].into_iter().filter(|s| *s != target).collect();\neditor.squash_commits(target, subjects, strategy)?;","handlingStrategy":"validation","validationCode":"let subjects: Vec<_> = subjects.into_iter().filter(|id| *id != target_id).collect();\neditor.squash_commits(target_id, subjects, strategy)?;","typeGuard":"fn distinct_from_target(target: &CommitSelector, s: &CommitSelector) -> bool { target != s }","tryCatchPattern":"match editor.squash_commits(target, subjects, strategy) {\n    Err(e) if e.to_string().contains(\"into itself\") => filter_target_from_subjects_and_retry(),\n    other => other,\n}","preventionTips":["Always exclude the target from the subjects list","Deduplicate subject selectors before squashing","Disallow selecting the same commit as both target and subject in tooling"],"tags":["git","squash","invalid-argument","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}