affaan-m/ECC · error
git commit failed
Error message
git commit failed: {stderr} What it means
Thrown when the `git commit -m <message>` subprocess exits non-zero. The library includes git's stderr verbatim so the underlying cause — identity not configured, hooks failing, GPG signing errors, lock contention — is visible. The commit itself did not happen.
Solutions
- Read the stderr embedded in the message; it names the exact git failure.
- Configure identity if stderr says 'Please tell me who you are': set user.name and user.email.
- If a hook failed, fix the hook violation or bypass temporarily with --no-verify (adjust the command or skip hooks in this wrapper).
- For gpg.signing errors, ensure the GPG key exists/unlocked, or disable commit.gpgsign.
- Remove a stale .git/index.lock only after confirming no other git process is running.
Example fix
// before: commit with no identity configured
commit_staged(&worktree, msg)?;
// after: ensure identity exists first
Command::new("git").args(["config", "user.name"]).status()?;
Command::new("git").args(["config", "user.email"]).status()?;
commit_staged(&worktree, msg)?; Defensive patterns
Strategy: try-catch
Validate before calling
fn git_identity_configured(worktree: &WorktreeInfo) -> bool {
Command::new("git").arg("-C").arg(&worktree.path)
.args(["config", "user.email"])
.output().map(|o| o.status.success()).unwrap_or(false)
} Type guard
None
Try / catch
match commit_staged(&worktree, &msg) {
Ok(hash) => println!("committed {hash}"),
Err(e) => {
let stderr = e.to_string();
if stderr.contains("who you are") { configure_identity_hint(); }
else if stderr.contains("hook") { show_hook_failure(&stderr); }
else { return Err(e); }
}
} Prevention
- Ensure user.name and user.email are configured before the first commit.
- Keep pre-commit hooks fast and deterministic, or document a bypass path.
- For signed repos, verify GPG keys are present and unlocked (or use SSH signing).
- Check for stale .git/index.lock after crashed git processes.
When it happens
Trigger: Calling commit_staged when git exits with failure: missing user.name/user.email, a pre-commit hook rejects the change, commit.gpgsign fails to sign, .git/index.lock is held, or the message triggers template issues.
Common situations: Fresh machine without git identity configured; company repos with mandatory commit-msg hooks; GPG keys absent or expired in signing setups; concurrent tooling (IDE + CLI) leaving index.lock behind.
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 reset failed for
- git restore failed for
- git rev-parse failed
- Base branch is not checked out in repo root (currently )
- branch name is not a valid git ref
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/b3c9284056473398.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/worktree/mod.rs:472
pub fn commit_staged(worktree: &WorktreeInfo, message: &str) -> Result<String> {
let message = message.trim();
if message.is_empty() {
anyhow::bail!("commit message cannot be empty");
}
if !has_staged_changes(worktree)? {
anyhow::bail!("no staged changes to commit");
}
let output = Command::new("git")
.arg("-C")
.arg(&worktree.path)
.args(["commit", "-m", message])
.output()
.context("Failed to create commit")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("git commit failed: {stderr}");
}
let rev_parse = Command::new("git")
.arg("-C")
.arg(&worktree.path)
.args(["rev-parse", "--short", "HEAD"])
.output()
.context("Failed to resolve commit hash")?;
if !rev_parse.status.success() {
let stderr = String::from_utf8_lossy(&rev_parse.stderr);
anyhow::bail!("git rev-parse failed: {stderr}");
}
Ok(String::from_utf8_lossy(&rev_parse.stdout)
.trim()
.to_string())
}
View on GitHub (pinned to 8321021c54)