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
- Run `git status --porcelain` to see the offending files, then `git add -A && git commit` them
- Run `git stash -u` to shelve changes, publish, then `git stash pop`
- Remove or gitignore stray untracked files (e.g. editor artifacts, temp files)
- 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
- Run `git status --porcelain` before any release command as a preflight check
- Keep .gitignore up to date for build artifacts and editor files
- Automate releases from CI on a freshly checked-out, clean tree
- Commit or stash WIP before starting release tooling
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
- git status command failed
- Command failed with status
- failed to generate evaluation example for commit
- failed to generate evaluation example for commit
- too many arguments
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)