xai-org/grok-build · error

working tree is not clean; commit before merging to '{target

Error message

working tree is not clean; commit before merging to '{target_branch}'

What it means

The merge_to_main flow requires a clean working tree before it merges the session branch into the target branch. Before merging it runs `git status --porcelain` and, if any output is present (uncommitted or untracked changes), fails with this error so the merge is never performed on a dirty tree.

Source

Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:3242

}
/// `MergeToMain` (`workspace.git_merge_to_main`): merge the conversation branch
/// into its target. Merge, never rebase; never force. On conflicts the merge
/// is aborted and HEAD is restored to `conv_branch` (never leave `MERGE_HEAD`
/// on the integration branch).
///
/// Fetch `origin/<target>` *before* checkout, then fast-forward the local
/// target so the deployed SHA can never be behind the durable remote tip; a
/// target that has *diverged* from origin is an error (never a force).
pub async fn merge_to_main(
    git_root: &Path,
    conv_branch: &str,
    target_branch: &str,
    push: bool,
) -> Result<GitMergeToMainResult> {
    ensure_ref_arg_safe(conv_branch, "session_branch")?;
    ensure_ref_arg_safe(target_branch, "target_branch")?;
    let dirty = git_cli(git_root, &["status", "--porcelain"]).await?;
    anyhow::ensure!(
        dirty.is_empty(),
        "working tree is not clean; commit before merging to '{target_branch}'"
    );
    let (fetched, _) = git_cli_raw(
        git_root,
        &["fetch", "origin", "--end-of-options", target_branch],
    )
    .await?;
    checkout_branch(git_root, target_branch, false).await?;
    if fetched
        && !git_cli_raw(
            git_root,
            &["merge-base", "--is-ancestor", "FETCH_HEAD", "HEAD"],
        )
        .await?
        .0
    {
        let (ff, ff_out) = git_cli_raw(git_root, &["merge", "--ff-only", "FETCH_HEAD"]).await?;

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Commit or stash all changes in the working tree (git add -A && git commit, or git stash), then re-run the operation.
  2. Remove or gitignore untracked build/generated artifacts so `git status --porcelain` is empty.
  3. If the changes belong to the session, commit them on the session branch first — that is what the flow expects.
  4. Run git status --porcelain yourself beforehand and surface a friendly prompt to the user to commit.

Example fix

// before
git_ops.merge_to_main(&root, "session/abc", "main", false).await?; // fails if dirty
// after
let dirty = Command::new("git").args(["status", "--porcelain"]).output()?;
if !dirty.stdout.is_empty() {
    Command::new("git").args(["add", "-A"]).status()?;
    Command::new("git").args(["commit", "-m", "session work"]).status()?;
}
git_ops.merge_to_main(&root, "session/abc", "main", false).await?;
Defensive patterns

Strategy: try-catch

Validate before calling

let status = Command::new("git").args(["status", "--porcelain"]).current_dir(&root).output()?;
anyhow::ensure!(status.stdout.is_empty(), "commit or stash changes before merging");

Try / catch

match git_ops.merge_to_main(&root, &branch, "main", false).await {
    Err(e) if e.to_string().contains("working tree is not clean") => {
        // prompt user to commit/stash, then retry once
        prompt_commit_and_retry()?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the merge-to-target operation (crates/codegen/xai-grok-workspace/src/session/git.rs:3242) while the git_root worktree has modified tracked files, staged-but-uncommitted changes, or untracked files — anything `git status --porcelain` reports.

Common situations: An agent/session left generated files or edits in the workspace without committing; the developer forgot to commit before triggering the merge; a tool (formatter, codegen step) wrote files into the repo between the last commit and the merge; .gitignore is missing so build artifacts show as untracked.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/4bcb9fccdf997dbd. Report an issue: GitHub.