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
- Push the whole stack from the bottom up (GitButler push of the stack) so remote ancestry matches the workspace, then create the review
- Force-push the outdated ancestor branches after the rebase/amend
- 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
- Push stacks as a unit instead of individual branches
- After rebasing or amending pushed commits, force-push all affected ancestors before reviewing
- Create reviews bottom-up so ancestors are always pushed first
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
- PR template exists but must be valid UTF-8 text or markdown
- Could not restore all review targets after the push failed:
- No Bitbucket access token found for account '{account_id}'.\
- Failed to create pull request: {status} - {error_text}
AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17).
Data as JSON: /api/errors/0d77c12b228cb937.
Report an issue: GitHub.