GitoxideLabs/gitoxide · error

rebasing would cause a merge conflict

Error message

rebasing would cause a merge conflict

What it means

When cherry-picking a tree change during a rebase, `cherry_pick_tree_outcome` may report `TreeRewrite::Conflict`. `cherry_pick_tree_checked` (this call site) converts that outcome into a hard error because a rebase that would produce merge conflicts cannot proceed automatically.

Solutions

  1. Resolve the conflict manually: perform the rebase interactively and fix the conflicting files at the conflicting commit.
  2. Rebase onto a different base that does not conflict with the commits being replayed.
  3. Recreate the commit(s) with changes merged against the new base before rebasing.
  4. Use a merge instead of a rebase for histories that genuinely conflict.

Example fix

// before: blind automatic rebase
let tree = cherry_pick_tree_checked(repo, old_base, new_base, tree)?; // bails on conflict
// after: probe the outcome first and handle conflicts
match cherry_pick_tree_outcome(repo, old_base, new_base, tree)? {
    TreeRewrite::Complete(t) => Ok(t),
    TreeRewrite::Conflict { .. } => prompt_user_to_resolve_and_retry(),
}?
Defensive patterns

Strategy: try-catch

Validate before calling

// probe the merge cleanly before committing to the rebase
let clean = matches!(
    cherry_pick_tree_outcome(repo, old_base, new_base, tree)?,
    TreeRewrite::Complete(_)
);

Try / catch

match cherry_pick_tree_checked(repo, old_base, new_base, tree) {
    Err(e) if e.to_string().contains("merge conflict") => {
        fall_back_to_interactive_resolution(repo, old_base, new_base)?
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling the rebase/cherry-pick helper with `old_base`, `new_base`, and `tree` ids such that applying the diff between `old_base` and `new_base` onto `tree` results in `TreeRewrite::Conflict { .. }` — the three-way merge is not clean (competing changes to the same paths).

Common situations: Rebasing a branch whose commits touch the same lines/files as commits on the new base; reordering commits that conflict with each other; rebasing after upstream force-push changed overlapping content.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/2001393df3c4b46b. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/rebase.rs:2701

    let new_base = parent_tree(repo, new_parents.first().copied())?;
    if commit.tree == old_base {
        return Ok(TreeRewrite::Complete(new_base));
    }
    if old_base == new_base {
        return Ok(TreeRewrite::Complete(commit.tree));
    }
    cherry_pick_tree_outcome(repo, old_base, new_base, commit.tree)
}

pub(super) fn cherry_pick_tree(
    repo: &gix::Repository,
    old_base: ObjectId,
    new_base: ObjectId,
    tree: ObjectId,
) -> Result<ObjectId> {
    match cherry_pick_tree_outcome(repo, old_base, new_base, tree)? {
        TreeRewrite::Complete(tree) => Ok(tree),
        TreeRewrite::Conflict { .. } => anyhow::bail!("rebasing would cause a merge conflict"),
    }
}

fn cherry_pick_tree_outcome(
    repo: &gix::Repository,
    old_base: ObjectId,
    new_base: ObjectId,
    tree: ObjectId,
) -> Result<TreeRewrite> {
    if tree == old_base {
        return Ok(TreeRewrite::Complete(new_base));
    }
    if old_base == new_base {
        return Ok(TreeRewrite::Complete(tree));
    }
    let labels = gix::merge::blob::builtin_driver::text::Labels {
        ancestor: Some(BStr::new(b"parent")),
        current: Some(BStr::new(b"rebased parent")),

View on GitHub (pinned to e73179060b)