GitoxideLabs/gitoxide · error

git checkout failed with

Error message

git checkout failed with {}

What it means

The `checkout` helper shells out to `git checkout`; when the subprocess exits with a nonzero status and its stderr is empty, tix reports only the process exit status because there is no stderr text to include. It surfaces that the external git command failed, without a diagnostic message.

Solutions

  1. Run the same `git checkout <args>` manually in the repo to see the real failure.
  2. Verify the branch/pin/review ref you are checking out actually exists (`git branch -a`, `git rev-parse <ref>`).
  3. Check `git status` for a dirty worktree blocking checkout and stash or commit first.
  4. Update git or check for repository corruption with `git fsck`.

Example fix

// before
checkout(&repo, &["checkout", "missing-branch"])?;
// -> "git checkout failed with exit status: 1"

// after
if repo.rev_parse_single("refs/heads/missing-branch").is_err() {
    eprintln!("branch does not exist");
} else {
    checkout(&repo, &["checkout", "missing-branch"])?;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the ref resolves and the worktree is clean before checkout
repo.rev_parse_single(&format!("refs/heads/{branch}"))
    .context("branch does not exist")?;
if !repo.is_dirty().unwrap_or(false) { checkout(&repo, &["checkout", branch])?; }

Try / catch

if let Err(e) = checkout(&repo, &["checkout", target]) {
    let msg = e.to_string();
    if msg.contains("git checkout failed with exit") && !msg.contains(": ") {
        // no stderr: rerun git checkout manually to capture the real cause
    }
    return Err(e.context("checkout failed"));
}

Prevention

When it happens

Trigger: Calling `checkout_review_return_reporting`, `checkout_branch`, `checkout_pin`, or `checkout_detached` when the spawned `git checkout` fails (non-success exit code) and produces no stderr output, e.g. git died abnormally or was killed.

Common situations: Checkout of a ref that doesn't exist where git's message went to stdout; git interrupted by a signal; odd git versions writing diagnostics elsewhere; a corrupted repository making git fail silently.

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 GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/6dcad74b52dbd22e. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/time_travel.rs:1340

        workdir,
        [OsString::from("--detach"), OsString::from(id.to_hex().to_string())],
    )
}

pub(super) fn checkout(workdir: &Path, args: impl IntoIterator<Item = OsString>) -> Result<()> {
    let output = Command::new("git")
        .arg("-C")
        .arg(workdir)
        .arg("checkout")
        .args(args)
        .output()
        .context("could not launch git checkout")?;
    if output.status.success() {
        return Ok(());
    }
    let stderr = output.stderr.trim().to_str_lossy();
    if stderr.is_empty() {
        anyhow::bail!("git checkout failed with {}", output.status)
    }
    anyhow::bail!("git checkout failed with {}: {}", output.status, stderr)
}

fn contains(repository: &gix::Repository, ancestor: ObjectId, descendant: ObjectId) -> bool {
    ancestor == descendant
        || repository
            .merge_base(ancestor, descendant)
            .is_ok_and(|base| base.as_ref() == ancestor)
}

pub(crate) fn pin_label(pin: &history::Pin) -> String {
    format!(
        "pin:{}",
        pin.name
            .as_bstr()
            .strip_prefix(history::PIN_PREFIX)
            .unwrap_or(pin.name.as_bstr())

View on GitHub (pinned to e73179060b)