gitbutlerapp/gitbutler · error
Found multiple matches for
Error message
Found multiple matches for {commit_id} What it means
When resolving a commit identifier against indexed stacks, the lookup expects at most one commit to match. If the iterator yields two or more commits with the same id across stacks/segments, the result is ambiguous and this error is thrown rather than guessing.
Solutions
- Run `but status` to see which stacks contain the commit; disambiguate by operating on the specific stack/branch instead of the bare id.
- Remove or de-duplicate the duplicated commit (unapply from one stack, or cherry-pick cleanup) and retry.
- Rebuild/refresh the workspace index so stale duplicate entries are cleared.
Defensive patterns
Strategy: try-catch
Validate before calling
// before resolving, inspect stacks for the id
let count = workspace.iter().filter(|c| c.commit_id() == commit_id).count();
if count > 1 { eprintln!("commit {} is duplicated across stacks; disambiguate first", commit_id); } Try / catch
match workspace.find_commit(commit_id) {
Err(e) if e.to_string().contains("Found multiple matches") => {
// pick the stack-scoped lookup instead
let c = stack.find_commit(commit_id)?;
}
other => other?,
} Prevention
- Run `but status` to check for the same commit in multiple stacks.
- Avoid cherry-picking the same commit into several managed stacks.
- Refresh the workspace index after operations that duplicate commits.
When it happens
Trigger: Looking up a commit id that appears in more than one stack or in multiple segments of the indexed workspace — e.g., the same commit was pushed/applied to two stacks, or duplicated by a workspace rebuild — so `matches.next()` returns `Some` twice.
Common situations: A cherry-pick or duplicate apply placed the same commit in two branches; stale workspace index containing overlapping stack entries; referring to a short id that collides across stacks.
Related errors
- commit prefix ' ' is ambiguous
- Could not find commit
- " " is ambiguous. Please provide more characters to…
- Aborting due to empty branch name
- Ad-hoc (single-branch) branch moves are not supported…
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/2c202a07d39c7ca0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/id/mod.rs:1803
/// Returns all known stacks.
pub fn stacks(&self) -> &Vec<StackWithId> {
self.indexed_stacks.borrow_owner()
}
/// Get a distinct commit by ID.
///
/// Errors if the commit cannot be found or if there are multiple matches.
pub fn get_commit_by_id(&self, commit_id: gix::ObjectId) -> anyhow::Result<CommitWithId<'_>> {
let mut matches = self
.commits()
.filter(|commit_with_id| match commit_with_id {
CommitWithId::Local(commit) => commit.commit_id() == commit_id,
CommitWithId::Remote(commit) => commit.commit_id() == commit_id,
});
match (matches.next(), matches.next()) {
(Some(commit), None) => Ok(commit),
(Some(_), Some(_)) => Err(anyhow::anyhow!("Found multiple matches for {commit_id}")),
_ => Err(anyhow::anyhow!("Could not find commit {commit_id}")),
}
}
fn commits(&self) -> impl Iterator<Item = CommitWithId<'_>> {
let stack_commits = self.indexed_stacks.borrow_owner().iter().flat_map(|stack| {
stack.segments.iter().flat_map(|segment| {
segment
.workspace_commits
.iter()
.map(CommitWithId::Local)
.chain(segment.remote_commits.iter().map(CommitWithId::Remote))
})
});
stack_commits.chain(
// Commits owned by a linked worktree resolve exactly like workspace commits - they
// just live outside the stacks.View on GitHub (pinned to 58e5313667)