zed-industries/zed · error

Working directory is not clean. Please commit or stash your…

Error message

Working directory is not clean. Please commit or stash your changes before publishing.

What it means

The GPUI publish xtask aborts when `git status --porcelain` reports any tracked-but-modified, staged, or untracked files. Publishing requires a clean tree so that version bumps and generated changes are reproducible and nothing unintended is mixed into the release. check_git_clean runs the git command via run_command and bails whenever the porcelain output is non-empty.

Solutions

  1. Run `git status --porcelain` to see the offending files, then `git add -A && git commit` them
  2. Run `git stash -u` to shelve changes, publish, then `git stash pop`
  3. Remove or gitignore stray untracked files (e.g. editor artifacts, temp files)
  4. Ensure the command is run from the intended workspace root, not a dirty copy of the repo

Example fix

// before (dirty tree)
$ cargo xtask publish-gpui
// Error: Working directory is not clean...

// after
$ git add -A && git commit -m "Prepare release"
$ cargo xtask publish-gpui
Defensive patterns

Strategy: validation

Validate before calling

let status = std::process::Command::new("git")
    .args(["status", "--porcelain"])
    .output()?;
if !String::from_utf8_lossy(&status.stdout).trim().is_empty() {
    anyhow::bail!("Commit or stash changes before publishing");
}

Type guard

fn is_git_clean() -> bool {
    let out = std::process::Command::new("git")
        .args(["status", "--porcelain"])
        .output()
        .map(|o| o.status.success());
    out.map(|ok| ok && std::str::from_utf8(&out.unwrap().stdout).map(|s| s.trim().is_empty()).unwrap_or(false)).unwrap_or(false)
}

Prevention

When it happens

Trigger: Running `cargo xtask publish-gpui` (run_publish_gpui -> check_git_clean) while the working tree has uncommitted modifications, staged changes, or untracked files. Also triggered if .gitignore is broken so stray files show in porcelain output.

Common situations: Developer edits Cargo.toml versions manually before publishing; leftover build artifacts or scratch files not gitignored; half-finished feature work in the repo when trying to cut a release.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


AI-assisted analysis of zed-industries/zed@916fc2b8cb (2026-09-19). Data as JSON: /api/errors/d21db83c75759c7d. Report an issue: GitHub.

Appendix: source

Thrown at tooling/xtask/src/tasks/gpui.rs:322

    Ok(())
}

fn check_git_clean() -> Result<()> {
    let output = run_command(
        Command::new("git")
            .args(["status", "--porcelain"])
            .stdout(Stdio::piped())
            .stderr(Stdio::piped()),
    )?;

    if !output.status.success() {
        bail!("git status command failed");
    }

    let stdout = String::from_utf8_lossy(&output.stdout);
    if !stdout.trim().is_empty() {
        bail!(
            "Working directory is not clean. Please commit or stash your changes before publishing."
        );
    }

    Ok(())
}

fn run_command(command: &mut Command) -> Result<Output> {
    let command_str = {
        let program = command.get_program().to_string_lossy();
        let args = command
            .get_args()
            .map(|arg| arg.to_string_lossy())
            .collect::<Vec<_>>()
            .join(" ");

        if args.is_empty() {
            program.to_string()

View on GitHub (pinned to 916fc2b8cb)