{"record":{"id":"ee11b6e1136da0fe","repo":"gitbutlerapp/gitbutler","slug":"need-at-least-2-commits-to-squash","errorCode":null,"errorMessage":"Need at least 2 commits to squash","messagePattern":"Need at least 2 commits to squash","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/commit/squash_commits.rs","lineNumber":146,"sourceCode":"///   commits' own change ranges.\n/// - A message determined by `how_to_combine_messages`:\n///   - `KeepTarget`: target message only.\n///   - `KeepSubject`: subject messages only.\n///   - `KeepBoth`: target message followed by subject messages.\n///\n/// Subject messages are appended in the order they are provided, with at least\n/// one blank line between non-empty message blocks.\n///\npub fn squash_commits<'ws, 'meta, M: RefMetadata, S: ToCommitSelector, T: ToCommitSelector>(\n    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","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-workspace/src/commit/squash_commits.rs#L128-L164","documentation":"Validation in squash_commits: squashing is defined as combining a target commit with at least one subject commit, so fewer than 2 commits is a no-op and is rejected. The caller must pass a subject list plus a target yielding at least two commits in total.","triggerScenarios":"Calling squash_commits with an empty subjects iterator (note: the message says 'at least 2' because target + subjects must total ≥ 2 commits).","commonSituations":"Batch scripts that collect commits to squash from a UI multi-select that came back empty; default-initialized vectors passed through.","solutions":["Pass at least one subject commit to squash into the target","Return early with a no-op or user-facing message when the selection is empty","Validate the selection count in the calling layer"],"exampleFix":"// before\neditor.squash_commits(target, Vec::new(), strategy)?;\n// after\nif subjects.is_empty() { bail!(\"select commits to squash\"); }\neditor.squash_commits(target, subjects, strategy)?;","handlingStrategy":"validation","validationCode":"if subjects.is_empty() {\n    bail!(\"select at least one commit to squash into the target\");\n}\neditor.squash_commits(target, subjects, strategy)?;","typeGuard":"fn squashable(target: gix::ObjectId, subjects: &[gix::ObjectId]) -> bool { !subjects.is_empty() }","tryCatchPattern":"match editor.squash_commits(target, subjects, strategy) {\n    Err(e) if e.to_string().contains(\"at least 2 commits\") => show_selection_required_message(),\n    other => other,\n}","preventionTips":["Require at least one subject in the squash UI/CLI","Guard empty multi-selects before invoking the API","Remember the target counts toward the two-commit minimum"],"tags":["git","squash","empty-input","validation"],"backgroundTag":"missing-required-argument","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"}