gitbutlerapp/gitbutler · error · anyhow::Error

commit prefix '{spec}' is ambiguous

Error message

commit prefix '{spec}' is ambiguous

What it means

Raised by `resolve_commit` when a commit spec is a prefix that matches two or more commits in the allowed divergence set (string prefix match against full hex ObjectIds). The parser refuses to guess which commit was meant.

Source

Thrown at crates/but-workspace/src/branch/integrate_branch_upstream/parsing.rs:161

                commit.target_relation,
                IntegrationDivergenceTargetRelation::NotIntegrated
            )
        })
        .map(|commit| commit.id)
        .chain(divergence.upstream_only.iter().map(|commit| commit.id))
        .collect()
}

fn resolve_commit(spec: &str, allowed_commits: &HashSet<gix::ObjectId>) -> Result<gix::ObjectId> {
    let matches = allowed_commits
        .iter()
        .copied()
        .filter(|commit_id| commit_id.to_string().starts_with(spec))
        .collect::<Vec<_>>();
    match matches.as_slice() {
        [] => bail!("commit '{spec}' is not part of the editable divergence"),
        [commit_id] => Ok(*commit_id),
        _ => bail!("commit prefix '{spec}' is ambiguous"),
    }
}

fn split_message_clause(line: &str) -> Result<(&str, Option<&str>)> {
    let Some((command_part, message_part)) = line.split_once('|') else {
        return Ok((line, None));
    };
    Ok((command_part.trim_end(), Some(message_part.trim_start())))
}

fn parse_message_clause(clause: &str) -> Result<String> {
    let value = clause
        .strip_prefix("message=")
        .context("expected `message=` after `|`")?;
    parse_quoted_string(value)
}

fn parse_quoted_string(input: &str) -> Result<String> {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Lengthen the prefix until it is unique (7+ hex chars is usually enough; full 40-char SHA always works).
  2. Copy the exact prefixes emitted by `render_integration_steps_script`, which uses `short_id` and is what the UI displays.

Example fix

# before
squash 4f 991b

# after
squash 4f2a9c1 991b3aa
Defensive patterns

Strategy: validation

Validate before calling

// Enforce unique prefixes up front:
fn unique_prefix_len(ids: &HashSet<gix::ObjectId>, spec: &str) -> bool {
    ids.iter().filter(|id| id.to_string().starts_with(spec)).count() == 1
}

Try / catch

if let Err(err) = parse_integration_steps_script(&script, &divergence) {
    if err.to_string().contains("ambiguous") {
        // ask user to lengthen the prefix on the reported line
    }
}

Prevention

When it happens

Trigger: Using a very short prefix like `4f` when two divergence commits both start with `4f`; prefixes shorter than the unique-prefix length of the current divergence.

Common situations: Users shorten SHAs to 1-4 chars as on CLI git; automated editors that truncate SHAs for readability.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/e7c53bc0f648c92b. Report an issue: GitHub.