GitoxideLabs/gitoxide · error · anyhow::Error

Tree conflicted, refusing to write commit

Error message

Tree conflicted, refusing to write commit

What it means

When a commit message was supplied (i.e. the merge is meant to produce a commit), the merge-tree operation refuses to write that commit if the merged tree still contains unresolved conflicts. Conflict paths are printed to stderr first so the caller can resolve them, then the command bails.

Solutions

  1. Inspect the conflict paths printed to stderr and resolve them (edit the tree, rerun with resolved inputs, or use `gix repo merge` with conflict resolution).
  2. Run without `--message` to obtain the conflicted tree/ids without attempting a commit, resolve manually, then commit yourself.
  3. Pick different base/ours/theirs revisions if the conflict stems from stale inputs.

Example fix

// before (automated commit despite conflicts)
gix repo merge tree --update-head --message "merge" <base> <ours> <theirs>
// after (let conflicts surface, resolve, then commit)
gix repo merge tree <base> <ours> <theirs>  # review conflicted paths
# resolve, then:
gix repo merge tree --update-head --message "merge" <base> <ours> <theirs>
Defensive patterns

Strategy: try-catch

Try / catch

match merge_tree(...) {
    Err(e) if e.to_string().contains("Tree conflicted, refusing to write commit") => {
        // read conflict paths from stderr, resolve, retry
    }
    r => r?,
}

Prevention

When it happens

Trigger: Running `gix repo merge tree --message ...` where `res.has_unresolved_conflicts(TreatAsUnresolved::default())` returns true for the merge result.

Common situations: Merging branches with genuinely conflicting hunks; re-running an automated merge after a previous partial resolution; conflicts involving file/directory collisions or rename/rename cases the resolver leaves open.

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/e2085d43fcbcddd7. Report an issue: GitHub.

Appendix: source

Thrown at gitoxide-core/src/repository/merge/tree.rs:90

                .into(),
            current: ours_ref
                .as_ref()
                .map_or(ours_id_str.as_str().into(), |n| n.as_bstr())
                .into(),
            other: theirs_ref
                .as_ref()
                .map_or(theirs_id_str.as_str().into(), |n| n.as_bstr())
                .into(),
        };
        let res = repo.merge_trees(base_id, ours_id, theirs_id, labels, options)?;
        let has_conflicts = !res.conflicts.is_empty();
        let has_unresolved_conflicts = res.has_unresolved_conflicts(TreatAsUnresolved::default());
        if message.is_some() && has_unresolved_conflicts {
            write_unresolved_conflict_paths(err, &res.conflicts)?;
            if debug {
                writeln!(err, "{:#?}", res.conflicts)?;
            }
            bail!("Tree conflicted, refusing to write commit");
        }

        let tree_id = {
            let _span = gix::trace::detail!("Writing merged tree");
            let mut written = 0;
            let tree_id = res
                .tree
                .detach()
                .write(|tree| {
                    written += 1;
                    repo.write(tree)
                })
                .map_err(|err| anyhow!("{err}"))?;
            writeln!(out, "{tree_id} (wrote {written} trees)")?;
            tree_id
        };

        let conflicts = res.conflicts;

View on GitHub (pinned to e73179060b)