nikivdev/code · error · anyhow::Error

git {} failed: {}

Error message

git {} failed: {}

What it means

`git_capture_in` runs a `git` subprocess with the given args and bails when git exits non-zero, formatting the full command and trimmed stderr into the message. It propagates any git failure (bad ref, not a repo, unknown revision) from all commit-info/explain call paths.

Source

Thrown at src/explain_commits.rs:111

    hasher.update(b"\n");
    hasher.update(message.as_bytes());
    hasher.update(b"\n");
    hasher.update(diff.as_bytes());
    format!("{:x}", hasher.finalize())
}

// -- Git helpers --

fn git_capture_in(repo_root: &Path, args: &[&str]) -> Result<String> {
    let output = Command::new("git")
        .current_dir(repo_root)
        .args(args)
        .output()
        .context("failed to run git")?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!("git {} failed: {}", args.join(" "), stderr.trim());
    }

    Ok(String::from_utf8_lossy(&output.stdout).to_string())
}

struct CommitInfo {
    sha: String,
    short_sha: String,
    message: String,
    subject: String,
    author: String,
    date: String,
    diff: String,
    files: Vec<String>,
}

fn get_commit_info(repo_root: &Path, sha: &str) -> Result<CommitInfo> {
    let short_sha = &sha[..7.min(sha.len())];

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the embedded stderr — it names the git-level cause (e.g. 'not a git repository', 'unknown revision')
  2. Run the command from inside a valid git repository (git rev-parse --git-dir to check)
  3. Verify the commit range/ref arguments exist: git log --oneline -5 or git rev-parse <ref>
  4. Ensure git is installed and on PATH
  5. Test the same git command manually to reproduce the failure

Example fix

// before
f explain-commits HEAD~99..HEAD   // git log HEAD~99..HEAD failed: fatal: ambiguous argument
// after
f explain-commits HEAD~5..HEAD    # range that exists in this repo
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight checks before running explain commands
if !std::path::Path::new(".git").exists() {
    bail!("not a git repository — run from a repo checkout");
}
let ok = std::process::Command::new("git")
    .args(["rev-parse", "--verify", "HEAD~5"])
    .status().map(|s| s.success()).unwrap_or(false);
if !ok { bail!("ref HEAD~5 does not exist in this repo"); }

Try / catch

match result {
    Err(e) if e.to_string().starts_with("git ") => {
        // message is "git {args} failed: {stderr}" — surface stderr to the user
        eprintln!("git failure: {e}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: `git_capture_in` is called (by get_commit_info, get_commits_in_range, get_last_n_commits, explain_new_commits_since, run_cli) and the spawned `git <args>` returns a non-success exit status; stderr text is embedded in the message.

Common situations: Running `f explain` outside a git repository; invalid commit range like `HEAD~50..HEAD` with too few commits; detached/unborn HEAD; git not on PATH produces the related 'failed to run git' context error instead; corrupt .git directory.

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 nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/ca4f77e646d8b343. Report an issue: GitHub.