GitoxideLabs/gitoxide · error

git stash push did not create a new stash

Error message

git stash push did not create a new stash

What it means

After running `git stash push`, `refs/stash` still points to the same commit it had before, meaning the stash operation silently did not create a new stash entry. The library detects this by comparing the pre-push `refs/stash` id with the post-push id and bails. This protects against editing the named state reference to point at a stale/unchanged stash commit.

Solutions

  1. Verify the working tree actually has uncommitted changes before saving.
  2. Inspect `git stash list` and `git rev-parse refs/stash` to see why the ref did not move.
  3. If the changes were already stashed, skip save or resume from the existing state instead.
Defensive patterns

Strategy: validation

Validate before calling

// Only save when there is something to stash
let dirty = !repo.status(gix::status::platform::prepare::Options::default())?.is_empty();
if !dirty { return Ok(()); } // nothing to stash; skip save

Try / catch

match result {
    Err(e) if e.to_string().contains("did not create a new stash") => {
        // treat as no-op: working tree was clean
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling save/save_manual when `git stash push` exits 0 but does not actually stash anything new (e.g. nothing to stash behavior, or the stash ref was manually reset), so `previous == Some(id)`.

Common situations: A clean working tree where git reports 'No local changes to save' yet exits successfully; hooks or config altering stash behavior; a previous stash push having already consumed the changes.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/4c508a2a0d2e1acc. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/stash.rs:230

    let output = Command::new("git")
        .arg("-C")
        .arg(workdir)
        .args(["stash", "push", "--include-untracked", "--quiet", "--message"])
        .arg(message)
        .output()
        .context("could not launch git stash push")?;
    if !output.status.success() {
        anyhow::bail!("git stash push failed: {}", output.stderr.trim().to_str_lossy());
    }

    let repo = open_repository(repository_path, bare, false).context("could not reopen repository after stashing")?;
    let mut stash = repo
        .try_find_reference("refs/stash")?
        .context("git stash push did not create refs/stash")?;
    let id = stash.peel_to_id()?.detach();
    if previous == Some(id) {
        anyhow::bail!("git stash push did not create a new stash");
    }
    let target = Target::Object(id);
    if let Err(err) = repo.edit_references([RefEdit::update(
        name.clone(),
        target.clone(),
        PreviousValue::MustNotExist,
        reflog_message,
    )]) {
        drop(repo);
        let restore = Command::new("git")
            .arg("-C")
            .arg(workdir)
            .args(["stash", "pop", "--index", "--quiet"])
            .output();
        return Err(anyhow::anyhow!(err)).context(match restore {
            Ok(output) if output.status.success() => {
                format!("could not retain {state_label}; original state was restored")
            }

View on GitHub (pinned to e73179060b)