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
- 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
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
- 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
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
- Need at least 2 commits to squash
- Aborting due to empty branch name
- Branch name ' ' collides with existing branch
- Can only check out local branches under refs/heads, got
- Can only check out local branches under refs/heads or…
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)