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
- 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.
- Discard repo-root changes if unwanted: `git -C <repo_root> checkout -- .` and remove untracked files that conflict.
- If untracked files are the cause, add them to .gitignore or move them out of the repo root.
- 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
- Treat the repo root as read-only while sessions are active — push agent work into worktrees only.
- gitignore build artifacts so they do not appear in git_status_short.
- Add a pre-merge hook that refuses to start when the repo root is dirty.
- Document the clean-root precondition in the merge command's user-facing help.
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
- Worktree {} has uncommitted changes; commit or discard them
- Base branch {} is not checked out in repo root (currently {}
- git merge-tree failed: {stderr}
- Merge blocked between {left_branch} and {right_branch} by {}
- Worktree {} has uncommitted changes; commit or discard them
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/b352b8b48f06ee07.
Report an issue: GitHub.