affaan-m/ECC · error

Repository root {} has uncommitted changes; commit or stash

Error message

Repository root {} has uncommitted changes; commit or stash them before merging

What it means

Thrown by merge_into_base at ecc2/src/worktree/mod.rs:882 after the base-branch check passes. It runs git_status_short(&repo_root) and bails if any entry comes back, because a `git merge` into a dirty working tree can fail mid-merge or silently interleave uncommitted edits with merge results. The repo root (resolved by base_checkout_path) must be clean before the merge command shells out.

Source

Thrown at ecc2/src/worktree/mod.rs:882

    if has_uncommitted_changes(worktree)? {
        anyhow::bail!(
            "Worktree {} has uncommitted changes; commit or discard them before merging",
            worktree.branch
        );
    }

    let repo_root = base_checkout_path(worktree)?;
    let current_branch = get_current_branch(&repo_root)?;
    if current_branch != worktree.base_branch {
        anyhow::bail!(
            "Base branch {} is not checked out in repo root (currently {})",
            worktree.base_branch,
            current_branch
        );
    }

    if !git_status_short(&repo_root)?.is_empty() {
        anyhow::bail!(
            "Repository root {} has uncommitted changes; commit or stash them before merging",
            repo_root.display()
        );
    }

    let output = Command::new("git")
        .arg("-C")
        .arg(&repo_root)
        .args(["merge", "--no-edit", &worktree.branch])
        .output()
        .context("Failed to merge worktree branch into base")?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        anyhow::bail!("git merge failed: {stderr}");
    }

    let merged_output = format!(

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Commit or stash changes in the repo root: `git -C <repo_root> stash` (or `git -C <repo_root> commit -am 'wip'`), then retry merge_into_base.
  2. Discard repo-root changes if unwanted: `git -C <repo_root> checkout -- .` and remove untracked files that conflict.
  3. If untracked files are the cause, add them to .gitignore or move them out of the repo root.
  4. Ensure no background processes (formatters, watchers, builds) are mutating the repo root during the merge.

Example fix

// before
merge_into_base(&worktree)?;

// after: pre-flight clean check
let repo_root = base_checkout_path(&worktree)?;
if !git_status_short(&repo_root)?.is_empty() {
    Command::new("git").arg("-C").arg(&repo_root)
        .args(["stash", "--include-untracked"]).status()?;
}
let outcome = merge_into_base(&worktree)?;
Defensive patterns

Strategy: validation

Validate before calling

fn repo_root_clean(repo_root: &Path) -> Result<bool> {
    Ok(git_status_short(repo_root)?.is_empty())
}

// before merge_into_base:
let repo_root = base_checkout_path(&worktree)?;
if !repo_root_clean(&repo_root)? {
    Command::new("git").arg("-C").arg(&repo_root)
        .args(["stash", "--include-untracked"]).status()?;
}

Type guard

null

Try / catch

match merge_into_base(&worktree) {
    Ok(o) => o,
    Err(e) if e.to_string().contains("has uncommitted changes") => {
        let repo_root = base_checkout_path(&worktree)?;
        let _ = Command::new("git").arg("-C").arg(&repo_root)
            .args(["stash", "--include-untracked"]).status();
        merge_into_base(&worktree)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling merge_into_base when the main checkout has staged or unstaged changes, untracked files that would be overwritten by the merge, or leftover artifacts from a prior merge/rebase. Also fires when an editor or build tool wrote to tracked files in the repo root between the branch check and the status check.

Common situations: Developer edited files in the main repo while an agent worked in its worktree; build tools regenerated lockfiles or dist artifacts in the repo root; a previous merge left conflict markers that were never resolved; untracked files (logs, coverage reports) collide with files incoming from the worktree branch.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/b352b8b48f06ee07. Report an issue: GitHub.