affaan-m/ECC · error · anyhow::Error
Worktree has uncommitted changes; commit or discard them…
Error message
Worktree {} has uncommitted changes; commit or discard them before merging What it means
merge_into_base refuses to run when the worktree has uncommitted changes (detected via has_uncommitted_changes). Merging with a dirty tree could lose or mix uncommitted work, so the library requires a clean worktree first.
Solutions
- Commit the pending changes in the worktree: `git -C <path> add -A && git commit`.
- Or stash them: `git -C <path> stash` and retry the merge.
- Discard unwanted changes with `git -C <path> restore .` if they are not needed.
- Run has_uncommitted_changes / git status in your own code before calling merge_into_base to fail earlier with a better UX.
- Add generated artifacts (build outputs) to .gitignore so tooling writes don't dirty the tree.
Example fix
// before
merge_into_base(&wt)?; // fails: dirty worktree
// after
Command::new("git").arg("-C").arg(&wt.path).args(["add","-A"]).status()?;
Command::new("git").arg("-C").arg(&wt.path).args(["commit","-m","wip"]).status()?;
merge_into_base(&wt)?; Defensive patterns
Strategy: validation
Validate before calling
if has_uncommitted_changes(&wt)? {
eprintln!("commit or stash changes in {} first", wt.branch);
return Ok(());
} Try / catch
if let Err(e) = merge_into_base(&wt) {
if e.to_string().contains("uncommitted changes") {
// prompt user to commit/stash, then retry
} else { return Err(e); }
} Prevention
- Commit or stash before switching tasks in a worktree
- Add generated artifacts to .gitignore
- Run has_uncommitted_changes as a precheck
- Automate auto-commit or stash in scripts that drive merges
When it happens
Trigger: Calling merge_into_base while the worktree has modified, staged, or untracked-but-tracked-index changes — e.g. edits made after the last commit in that worktree.
Common situations: Developer left WIP edits in the worktree; an editor or formatter auto-modified files; tests wrote artifacts into the worktree directory.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Base branch is not checked out in repo root (currently )
- cannot reset a staged hunk while the file also has unstaged…
- git log failed
- git reset failed for
- git restore failed for
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/cbe750a9421ab6a3.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/worktree/mod.rs:865
pub fn has_uncommitted_changes(worktree: &WorktreeInfo) -> Result<bool> {
Ok(!git_status_short(&worktree.path)?.is_empty())
}
pub fn has_staged_changes(worktree: &WorktreeInfo) -> Result<bool> {
Ok(git_status_entries(worktree)?
.iter()
.any(|entry| entry.staged))
}
pub fn merge_into_base(worktree: &WorktreeInfo) -> Result<MergeOutcome> {
let readiness = merge_readiness(worktree)?;
if readiness.status == MergeReadinessStatus::Conflicted {
anyhow::bail!(readiness.summary);
}
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",View on GitHub (pinned to 8321021c54)