gitbutlerapp/gitbutler · error

Cannot squash a commit into itself

Error message

Cannot squash a commit into itself

What it means

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.

Solutions

  1. Remove the target commit from the subjects list before calling
  2. Pick a different target commit that is not among the subjects
  3. Filter subjects: subjects.retain(|s| s != target) before invoking

Example fix

// before
editor.squash_commits(target, vec![target, other], strategy)?; // target in subjects
// after
let subjects: Vec<_> = vec![target, other].into_iter().filter(|s| *s != target).collect();
editor.squash_commits(target, subjects, strategy)?;
Defensive patterns

Strategy: validation

Validate before calling

let subjects: Vec<_> = subjects.into_iter().filter(|id| *id != target_id).collect();
editor.squash_commits(target_id, subjects, strategy)?;

Type guard

fn distinct_from_target(target: &CommitSelector, s: &CommitSelector) -> bool { target != s }

Try / catch

match editor.squash_commits(target, subjects, strategy) {
    Err(e) if e.to_string().contains("into itself") => filter_target_from_subjects_and_retry(),
    other => other,
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/59691250e074260d. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-workspace/src/commit/squash_commits.rs:156

    editor: Editor<'ws, 'meta, M>,
    subjects: Vec<S>,
    target_commit: T,
    how_to_combine_messages: MessageCombinationStrategy,
) -> Result<SquashCommitsOutcome<'ws, 'meta, M>> {
    let mut seen_subjects = std::collections::HashSet::with_capacity(subjects.len());

    if subjects.is_empty() {
        bail!("Need at least 2 commits to squash")
    }

    let (target_commit_selector, target_commit_obj) =
        editor.find_selectable_commit(target_commit)?;

    let mut subject_selectors = Vec::with_capacity(subjects.len());
    for subject_commit in subjects {
        let (subject_commit_selector, _) = editor.find_selectable_commit(subject_commit)?;
        if subject_commit_selector == target_commit_selector {
            bail!("Cannot squash a commit into itself")
        }
        if !seen_subjects.insert(subject_commit_selector) {
            continue;
        }
        subject_selectors.push(subject_commit_selector);
    }

    let subject_commit_ids = subject_selectors
        .iter()
        .map(|commit_selector| {
            let (_, commit) = editor.find_selectable_commit(*commit_selector)?;
            Ok(commit.id)
        })
        .collect::<Result<Vec<_>>>()?;
    let squashed_tree = editor.merge_commit_changes_to_tree(
        target_commit_obj.id,
        subject_commit_ids,
        editor.repo().merge_options_force_ours()?,

View on GitHub (pinned to 58e5313667)