affaan-m/ECC · error

Worktree {} has uncommitted changes; commit or discard them

Error message

Worktree {} has uncommitted changes; commit or discard them before rebasing

What it means

Thrown by rebase_onto_base at ecc2/src/worktree/mod.rs:915 as the very first guard. It calls has_uncommitted_changes(worktree) (which runs git status --porcelain in the worktree path) and bails if anything is dirty, because `git rebase <base_branch>` requires a clean working tree — git itself would refuse or, worse, stash-and-partially-replay.

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 01e15490f0)

Solutions

  1. Commit the worktree's changes first: `git -C <worktree_path> add -A && git -C <worktree_path> commit -m 'wip'`, then retry rebase_onto_base.
  2. If the changes are unwanted, discard them: `git -C <worktree_path> checkout -- .` (and clean untracked files if appropriate).
  3. If you want to keep edits but not commit, git stash inside the worktree before rebasing and pop after: `git -C <worktree_path> stash`.
  4. Ensure ECC's session lifecycle commits agent edits before exposing a rebase entry point.

Example fix

// before
rebase_onto_base(&worktree)?;

// after: auto-commit dirty worktree before rebasing
if has_uncommitted_changes(&worktree)? {
    Command::new("git").arg("-C").arg(&worktree.path)
        .args(["add", "-A"]).status()?;
    Command::new("git").arg("-C").arg(&worktree.path)
        .args(["commit", "-m", "wip: pre-rebase snapshot"]).status()?;
}
rebase_onto_base(&worktree)?;
Defensive patterns

Strategy: validation

Validate before calling

if has_uncommitted_changes(&worktree)? {
    Command::new("git").arg("-C").arg(&worktree.path)
        .args(["add", "-A"]).status()?;
    Command::new("git").arg("-C").arg(&worktree.path)
        .args(["commit", "-m", "chore: snapshot before rebase"]).status()?;
}
// now safe to call rebase_onto_base

Type guard

null

Try / catch

match rebase_onto_base(&worktree) {
    Ok(o) => o,
    Err(e) if e.to_string().contains("uncommitted changes; commit or discard them before rebasing") => {
        Command::new("git").arg("-C").arg(&worktree.path)
            .args(["add", "-A"]).status()?;
        Command::new("git").arg("-C").arg(&worktree.path)
            .args(["commit", "-m", "wip"]).status()?;
        rebase_onto_base(&worktree)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling rebase_onto_base on a worktree where the agent left uncommitted edits; an editor or build tool modified tracked files inside the worktree path; staged changes exist (git status -s returns non-empty); untracked files are present (status --porcelain lists them with ??).

Common situations: Agent session wrote code to the worktree but did not commit before the user invoked rebase; formatter reformatted files on save after the last commit; leftover conflict markers from a previous rebase attempt; build artifacts (dist/, target/) are tracked or appear as untracked-but-relevant.

Related errors


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