{"record":{"id":"c90e32264fc0d419","repo":"affaan-m/ECC","slug":"worktree-has-uncommitted-changes-commit-or-dis-c90e32","errorCode":null,"errorMessage":"Worktree {} has uncommitted changes; commit or discard them before rebasing","messagePattern":"Worktree (.+?) has uncommitted changes; commit or discard them before rebasing","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"ecc2/src/worktree/mod.rs","lineNumber":915,"sourceCode":"        anyhow::bail!(\"git merge failed: {stderr}\");\n    }\n\n    let merged_output = format!(\n        \"{}\\n{}\",\n        String::from_utf8_lossy(&output.stdout),\n        String::from_utf8_lossy(&output.stderr)\n    );\n\n    Ok(MergeOutcome {\n        branch: worktree.branch.clone(),\n        base_branch: worktree.base_branch.clone(),\n        already_up_to_date: merged_output.contains(\"Already up to date.\"),\n    })\n}\n\npub fn rebase_onto_base(worktree: &WorktreeInfo) -> Result<RebaseOutcome> {\n    if has_uncommitted_changes(worktree)? {\n        anyhow::bail!(\n            \"Worktree {} has uncommitted changes; commit or discard them before rebasing\",\n            worktree.branch\n        );\n    }\n\n    let repo_root = base_checkout_path(worktree)?;\n    let before_head = branch_head_oid_in_repo(&repo_root, &worktree.branch)?;\n    let output = Command::new(\"git\")\n        .arg(\"-C\")\n        .arg(&worktree.path)\n        .args([\"rebase\", &worktree.base_branch])\n        .output()\n        .context(\"Failed to rebase worktree branch onto base\")?;\n\n    if !output.status.success() {\n        let abort_output = Command::new(\"git\")\n            .arg(\"-C\")\n            .arg(&worktree.path)","sourceCodeStart":897,"sourceCodeEnd":933,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/worktree/mod.rs#L897-L933","documentation":"`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.","triggerScenarios":"Calling rebase_onto_base on a WorktreeInfo whose working tree contains modified, staged, or untracked-but-relevant files that make the tree dirty.","commonSituations":"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.","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"],"exampleFix":"// before: rebase with dirty tree -> error\nrebase_onto_base(&wt)?;\n// after: ensure clean tree first\nanyhow::ensure!(\n    !has_uncommitted_changes(&wt)?,\n    \"commit or stash changes in worktree {} first\",\n    wt.branch\n);\nrebase_onto_base(&wt)?;","handlingStrategy":"validation","validationCode":"let status = Command::new(\"git\")\n    .args([\"status\", \"--porcelain\"])\n    .current_dir(&wt.path)\n    .output()?;\nlet clean = status.stdout.is_empty();\nanyhow::ensure!(clean, \"commit or stash changes in worktree {} first\", wt.branch);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["git","rebase","precondition","dirty-worktree"],"backgroundTag":"invalid-state-transition","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}