gitbutlerapp/gitbutler · error

Branch `{}` is pushed, but its remote ancestry does not matc

Error message

Branch `{}` is pushed, but its remote ancestry does not match the reviewed workspace stack; push it and its ancestors before creating a review

What it means

Before creating a review, GitButler verifies that the remote tips of the reviewed ancestor branches plus the selected branch form a chain: each pair is checked with remote_contains, so each ancestor's remote tip must contain its parent's tip. A broken pair means remote history no longer matches the reviewed workspace stack, and review creation stops.

Source

Thrown at crates/but-api/src/legacy/forge.rs:1886

    let repo = ctx.repo.get()?;

    let mut reviewed_ancestors = stack.segments[selected_index + 1..]
        .iter()
        .rev()
        .filter(|segment| review_number(segment).is_some())
        .map(|segment| remote_head(&repo, segment))
        .collect::<Result<Vec<_>>>()?;
    let selected = remote_head(&repo, &stack.segments[selected_index])?;

    for pair in reviewed_ancestors
        .iter()
        .map(|head| head.remote_tip)
        .chain(std::iter::once(selected.remote_tip))
        .collect::<Vec<_>>()
        .windows(2)
    {
        if !remote_contains(&repo, pair[0], pair[1])? {
            anyhow::bail!(
                "Branch `{}` is pushed, but its remote ancestry does not match the reviewed workspace stack; push it and its ancestors before creating a review",
                branch.shorten()
            );
        }
    }

    match reviewed_ancestors.pop() {
        Some(nearest_reviewed_ancestor) => Ok(nearest_reviewed_ancestor.branch_name),
        None => target_short_name(&ctx.project_meta()?, &repo),
    }
}

#[derive(Debug)]
struct RemoteHead {
    branch_name: String,
    remote_tip: gix::ObjectId,
}

View on GitHub (pinned to 2497b8007a)

Solutions

  1. Push the whole stack from the bottom up (GitButler push of the stack) so remote ancestry matches the workspace, then create the review
  2. Force-push the outdated ancestor branches after the rebase/amend
  3. Verify all segments up to the workspace base are pushed before selecting the branch for review

Example fix

# before: review a branch whose ancestors are stale on the remote
but review create my-branch   # fails: ancestry mismatch

# after: push the stack including ancestors first, then review
but push --stack my-stack
but review create my-branch
Defensive patterns

Strategy: validation

Validate before calling

let tips: Vec<gix::ObjectId> = reviewed_ancestor_tips.iter()
    .map(|h| h.remote_tip)
    .chain(std::iter::once(selected_tip))
    .collect();
for pair in tips.windows(2) {
    if !remote_contains(&repo, pair[0], pair[1])? {
        // push the stack (with ancestors) before creating the review
    }
}

Type guard

fn remote_ancestry_is_chain(
    tips: &[gix::ObjectId],
    contains: impl Fn(&gix::ObjectId, &gix::ObjectId) -> bool,
) -> bool {
    tips.windows(2).all(|p| contains(&p[0], &p[1]))
}

Try / catch

match create_review(ctx, branch).await {
    Err(err) if err.to_string().contains("remote ancestry does not match") => {
        // prompt: push the full stack (ancestors included) and retry
    }
    other => other,
}

Prevention

When it happens

Trigger: Ancestor branches were pushed earlier from different commits — segments pushed independently, bottom commits rebased or amended after a previous push, or branches from different stacks mixed into one review — so a parent's remote tip is not contained in the child's remote tip.

Common situations: User amends or rebases lower commits after pushing; pushes individual branches rather than the whole stack; force-pushes only some ancestors; reviews spanning segments pushed out of order.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17). Data as JSON: /api/errors/0d77c12b228cb937. Report an issue: GitHub.