affaan-m/ECC · error · anyhow::Error
git merge-tree failed: {stderr}
Error message
git merge-tree failed: {stderr} What it means
merge_readiness_for_branches runs `git merge-tree --write-tree <left> <right>` (the modern git 2.38+ form). If git exits non-zero AND the output yielded zero parseable conflict paths, the function gives up and bails with git's stderr. The 'conflicts but no conflict lines' branch means git failed outright rather than reporting a merge conflict.
Source
Thrown at ecc2/src/worktree/mod.rs:808
let overflow = conflicts.len().saturating_sub(3);
let detail = if overflow > 0 {
format!("{conflict_summary}, +{overflow} more")
} else {
conflict_summary
};
return Ok(MergeReadiness {
status: MergeReadinessStatus::Conflicted,
summary: format!(
"Merge blocked between {left_branch} and {right_branch} by {} conflict(s): {detail}",
conflicts.len()
),
conflicts,
});
}
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("git merge-tree failed: {stderr}");
}
pub fn branch_conflict_preview(
left: &WorktreeInfo,
right: &WorktreeInfo,
max_lines: usize,
) -> Result<Option<BranchConflictPreview>> {
if left.base_branch != right.base_branch {
return Ok(None);
}
let repo_root = base_checkout_path(left)?;
let readiness = merge_readiness_for_branches(&repo_root, &left.branch, &right.branch)?;
if readiness.status != MergeReadinessStatus::Conflicted {
return Ok(None);
}
Ok(Some(BranchConflictPreview {View on GitHub (pinned to 01e15490f0)
Solutions
- Confirm git >= 2.38: `git --version`; bump the image if older.
- Verify both refs resolve locally: `git rev-parse --verify <left>` and `git rev-parse --verify <right>`.
- Run `git fetch --all` (or fetch the base) so the base_branch ref is present.
- Run `git fsck` if refs resolve but merge-tree still errors.
Example fix
// before
let readiness = merge_readiness_for_branches(&root, &base, &branch)?;
// after
// ensure both refs resolve before asking merge-tree about them
for r in [&base, &branch] {
let ok = Command::new("git").arg("-C").arg(&root)
.args(["rev-parse", "--verify", r]).output()?.status.success();
if !ok { anyhow::bail!("ref does not exist: {r}"); }
}
let readiness = merge_readiness_for_branches(&root, &base, &branch)?; Defensive patterns
Strategy: validation
Validate before calling
use std::process::Command;
fn git_supports_write_tree() -> bool {
// merge-tree --write-tree landed in git 2.38
let out = Command::new("git").arg("--version").output();
matches!(out, Ok(o) if String::from_utf8_lossy(&o.stdout).contains("git version 2.38")
|| newer_than_2_38(&String::from_utf8_lossy(&o.stdout)))
}
fn both_refs_resolve(root: &Path, left: &str, right: &str) -> bool {
for r in [left, right] {
let ok = Command::new("git").arg("-C").arg(root)
.args(["rev-parse", "--verify", r]).output()
.map(|o| o.status.success()).unwrap_or(false);
if !ok { return false; }
}
true
}
if !git_supports_write_tree() { anyhow::bail!("git >= 2.38 required for merge readiness"); }
if !both_refs_resolve(&root, left, right) { anyhow::bail!("one or both refs do not exist locally"); }
let readiness = merge_readiness_for_branches(&root, left, right)?; Try / catch
match merge_readiness_for_branches(&root, left, right) {
Ok(r) => Ok(r),
Err(e) => {
let m = format!("{e:#}");
if m.contains("usage: git merge-tree") || m.contains("unknown option") {
// ancient git; fall back to a dry-run merge in a temp worktree
} else if m.contains("Not a valid object name") {
// fetch and retry once
}
Err(e)
}
} Prevention
- Pin CI/runtime images to git >= 2.38 if you use merge-readiness features.
- Always `git fetch` the base branch before computing readiness so the ref is present.
- Run `git fsck` if both refs resolve but merge-tree still errors.
When it happens
Trigger: Either branch ref does not exist; git version is older than 2.38 and does not support `merge-tree --write-tree`; object database corruption; refs are missing because fetch/pull never happened for one side.
Common situations: CI image pinned to an old git (e.g. 2.30); worktree branch not yet pushed so the ref is unknown to a shallow/partial clone; `base_branch` was deleted on the remote; corrupted loose object after interrupted gc.
Related errors
- git worktree add failed: {stderr}
- git status failed: {stderr}
- git add failed for {path}: {stderr}
- git reset failed for {path}: {stderr}
- git restore failed for {}: {stderr}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/7a7eb6731553c0fe.
Report an issue: GitHub.