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 rebasing What it means
`rebase_onto_base` refuses to run when the worktree has uncommitted changes, detected via `has_uncommitted_changes`. Rebasing with a dirty tree would lose or interleave edits, so the library bails with an explicit guard error naming the branch. It is a deliberate precondition check, not a git failure.
Solutions
- Commit the changes in the worktree: 'git add -A && git commit -m "wip before rebase"'
- Discard unwanted changes: 'git restore .' (tracked) or 'git clean -fd' (untracked)
- Stash them: 'git stash' then rebase, then 'git stash pop'
- Fix the build process that is dirtying files (e.g. generated lockfiles) so the tree stays clean
Example fix
// before: rebase with dirty tree -> error
rebase_onto_base(&wt)?;
// after: ensure clean tree first
anyhow::ensure!(
!has_uncommitted_changes(&wt)?,
"commit or stash changes in worktree {} first",
wt.branch
);
rebase_onto_base(&wt)?; Defensive patterns
Strategy: validation
Validate before calling
let status = Command::new("git")
.args(["status", "--porcelain"])
.current_dir(&wt.path)
.output()?;
let clean = status.stdout.is_empty();
anyhow::ensure!(clean, "commit or stash changes in worktree {} first", wt.branch); Prevention
- Always commit or stash before invoking rebase operations
- Enable the tool's dirty-tree pre-check (git status --porcelain) in any automation
- Avoid generated files inside worktrees, or gitignore them
- Commit WIP with a marker message instead of leaving edits uncommitted
When it happens
Trigger: Calling rebase_onto_base on a WorktreeInfo whose working tree contains modified, staged, or untracked-but-relevant files that make the tree dirty.
Common situations: A developer edited files inside the worktree but forgot to commit before clicking rebase; a build artifact or lockfile changed on disk; an editor auto-saved a file mid-session.
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 rebase failed
- no staged changes to commit
- Repository root has uncommitted changes; commit or stash…
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/c90e32264fc0d419.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/worktree/mod.rs:915
anyhow::bail!("git merge failed: {stderr}");
}
let merged_output = format!(
"{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
Ok(MergeOutcome {
branch: worktree.branch.clone(),
base_branch: worktree.base_branch.clone(),
already_up_to_date: merged_output.contains("Already up to date."),
})
}
pub fn rebase_onto_base(worktree: &WorktreeInfo) -> Result<RebaseOutcome> {
if has_uncommitted_changes(worktree)? {
anyhow::bail!(
"Worktree {} has uncommitted changes; commit or discard them before rebasing",
worktree.branch
);
}
let repo_root = base_checkout_path(worktree)?;
let before_head = branch_head_oid_in_repo(&repo_root, &worktree.branch)?;
let output = Command::new("git")
.arg("-C")
.arg(&worktree.path)
.args(["rebase", &worktree.base_branch])
.output()
.context("Failed to rebase worktree branch onto base")?;
if !output.status.success() {
let abort_output = Command::new("git")
.arg("-C")
.arg(&worktree.path)View on GitHub (pinned to 8321021c54)