KhueApps
Home/DevOps/Fixing 'fatal: HEAD is not a valid object' in Git

Fixing 'fatal: HEAD is not a valid object' in Git

Last updated: October 07, 2025

Overview

The error “fatal: HEAD is not a valid object” means Git cannot resolve the name HEAD to a commit. This happens when a repository has no commits yet, when HEAD points to a branch that does not exist, or when refs are corrupted/missing (common in CI, bare repos, or after manual edits in .git).

Exact wording varies by Git version and command. You might also see:

  • fatal: bad object HEAD
  • fatal: ambiguous argument 'HEAD'

The fixes below cover all common DevOps/Git scenarios.

Quickstart (most common fixes)

  • New repo with no commits: create the initial commit.
  • Default branch missing/renamed: point HEAD to an existing branch.
  • Broken HEAD file: recreate HEAD as a symbolic ref.
  • Repo missing local commits but has a remote: fetch and reset to a remote branch.

Minimal commands:

# Case A: No commits yet
git add -A
git commit -m "Initial commit"

# OR create an empty initial commit
git commit --allow-empty -m "Initial commit"

# Case B: HEAD points to a non-existent branch; set to main (or your branch)
git symbolic-ref HEAD refs/heads/main

# Case C: Recover from remote
git fetch --all --prune
git checkout -B main origin/main

Minimal working example (reproduce and fix)

Reproduce a broken HEAD referencing a missing branch:

mkdir demo && cd demo
git init
# Make a real commit so HEAD resolves initially
printf "hello\n" > file.txt
git add file.txt
git commit -m "init"

# Create main, then point HEAD to it
git branch -M main

# Simulate a broken ref: delete the branch ref
rm -f .git/refs/heads/main

# Now HEAD cannot resolve to a commit
# Many commands will fail similarly
( git rev-parse --verify HEAD ) || echo "HEAD is broken"

# Fix: point HEAD to an existing commit by recreating the branch
last=$(git show-ref -s --heads | head -n1)
# If none, fetch a remote or create a new commit

git update-ref refs/heads/main "$last" || git commit --allow-empty -m "re-anchor"

git symbolic-ref HEAD refs/heads/main

# Verify
git rev-parse --verify HEAD
git status

Notes:

  • Depending on your Git version, errors may read “fatal: HEAD is not a valid object,” “fatal: bad object HEAD,” or “ambiguous argument 'HEAD'.”
  • In CI/bare repos, prefer the simpler recovery recipes in the next section.

Diagnose before fixing

  1. Check if HEAD resolves:
    git rev-parse --verify HEAD
    
    • Exit code 0: HEAD is fine. The error came from a different cause/command.
    • Non‑zero: proceed.
  2. List local branches/refs:
    git show-ref --heads
    git branch -vv
    
  3. Check the HEAD file:
    cat .git/HEAD
    
    Expect: ref: refs/heads/main (or your default branch). If it’s missing or not a ref: line, it’s broken.
  4. If you have a remote:
    git remote -v
    git ls-remote --heads origin
    
  5. Confirm if there are zero commits:
    git log --oneline -1 || echo "No commits yet"
    

Fix by scenario

A) Repository has no commits yet

Symptom: new repo, git log says “your current branch ... does not have any commits yet,” or HEAD resolution fails.

Fix:

git add -A
git commit -m "Initial commit"
# or
git commit --allow-empty -m "Initial commit"

B) HEAD points to a missing/renamed branch

Symptom: .git/HEAD contains ref: refs/heads/main but refs/heads/main does not exist (branch renamed or deleted).

Fix (choose one):

  • Point HEAD to an existing branch:
    git symbolic-ref HEAD refs/heads/master   # if master exists
    
  • Recreate the branch from the latest known commit:
    last=$(git show-ref -s --heads | head -n1)
    git update-ref refs/heads/main "$last"
    git symbolic-ref HEAD refs/heads/main
    
  • If you have a remote default branch:
    git fetch --all --prune
    git checkout -B main origin/main
    

C) Broken or missing HEAD file

Symptom: .git/HEAD missing or contains a raw commit hash (not a symbolic ref) when you expect a branch.

Fix (set HEAD to your default branch):

echo "ref: refs/heads/main" > .git/HEAD
# If refs/heads/main is absent, create it from a commit or remote.

D) Detached HEAD pointing at a missing commit

Symptom: you were in detached HEAD and the object was garbage-collected or never fetched.

Fix:

git fetch --all --prune
# Reattach to a branch that exists on the remote
git checkout -B main origin/main

E) Bare repositories (servers, CI caches)

Symptom: bare repo with incorrect default branch pointer.

Fix:

# In the bare repo directory (contains HEAD and objects but no working tree)
git symbolic-ref HEAD refs/heads/main

Verification checklist

  • git rev-parse --verify HEAD returns a commit ID.
  • git status shows a branch name (not detached unless intentionally).
  • git log -1 --oneline prints the latest commit.

Pitfalls and safety

  • Destructive commands:
    • git reset --hard discards local changes. Avoid using it as a “fix.”
    • Editing files in .git can corrupt refs if mistaken. Prefer git symbolic-ref and git update-ref.
  • Branch names:
    • Match your environment (main vs master). Don’t assume.
  • CI considerations:
    • Ensure the checkout step fetches the target ref. For shallow clones, include the branch commit you need (e.g., fetch-depth: 0).
  • Remote mismatch:
    • If the default branch changed, update HEAD or your checkout scripts accordingly.

Performance notes

  • git fetch --all --prune can be network‑heavy; fetch only the branch you need:
    git fetch origin main:main
    
  • git fsck is thorough but slow on large repos. Use it only when corruption is suspected.
  • To resolve HEAD quickly without scanning all refs, jump directly to a known commit or remote ref (e.g., origin/main).
  • Avoid repeated git gc in CI; rely on scheduled maintenance instead.

Tiny FAQ

  • Q: Why does this happen right after git init? A: There’s no commit yet; create the initial commit so HEAD can point to one.

  • Q: Our default branch changed from master to main. What now? A: Update HEAD: git symbolic-ref HEAD refs/heads/main, and ensure the branch exists locally or fetch it.

  • Q: Can I just run git reset --hard HEAD to fix it? A: No. If HEAD is invalid, that command fails and may hide the real issue. Fix HEAD first.

  • Q: Is my history lost? A: Usually no. If commits exist in the remote or other refs, fetch/reset to them. Only missing objects combined with expired reflogs risk data loss.

  • Q: How do I detect this early in CI? A: Add a guard step: git rev-parse --verify HEAD || exit 1 and fix the checkout or HEAD ref when it fails.

Series: Git

DevOps