🔧 Error Fixes
· 2 min read
Last updated on

Git: Cannot Lock Ref — How to Fix It


You try to pull, fetch, or checkout a branch and Git throws:

error: cannot lock ref 'refs/heads/main': Unable to create lock file

Or the related variant:

fatal: Unable to create '/path/to/repo/.git/refs/heads/main.lock': File exists

Git uses lock files to prevent concurrent operations from corrupting refs. If a lock file is stuck, everything grinds to a halt.

What causes this

When Git updates a reference (branch pointer, tag, etc.), it creates a .lock file next to the ref file. This prevents two Git processes from writing to the same ref simultaneously. Once the operation completes, the lock file is removed.

The lock file gets stuck when:

  • A previous Git operation crashed or was killed mid-write (Ctrl+C during a rebase, power loss, etc.)
  • Another Git process is still running (a background fetch, a GUI client, an IDE’s Git integration)
  • A filesystem issue prevents Git from deleting the lock file
  • On networked filesystems (NFS, SMB), stale locks can persist after a client disconnects

Fix 1: Remove the stale lock file

If you’re sure no other Git process is running, delete the lock file:

rm -f .git/refs/heads/main.lock

If you’re not sure which lock file is the problem, find all of them:

find .git -name "*.lock" -type f

Then remove them:

find .git -name "*.lock" -type f -delete

Always verify no other Git process is running first:

ps aux | grep git

Fix 2: Run garbage collection

Sometimes the issue is caused by loose refs or packed-refs being in a bad state. Running GC cleans things up:

git gc --prune=now

If that also fails due to a lock, remove the lock first (Fix 1), then run GC.

Fix 3: Prune stale remote refs

If the error mentions a remote ref like refs/remotes/origin/main, the issue is with your local copy of remote tracking branches:

git remote prune origin

This removes local references to remote branches that no longer exist. If that fails due to a lock:

rm -f .git/refs/remotes/origin/main.lock
git remote prune origin

Fix 4: Re-pack references

Git stores refs in two ways: as individual files under .git/refs/ and packed into .git/packed-refs. Conflicts between these can cause lock issues:

git pack-refs --all

This consolidates all loose refs into the packed-refs file, which can resolve conflicts between the two storage formats.

Fix 5: Check for background Git processes

IDEs like VS Code, IntelliJ, and others run Git operations in the background. If you’re seeing lock errors frequently:

# Check for running Git processes
ps aux | grep git

# On macOS/Linux, check what's holding the lock
lsof .git/refs/heads/main.lock

Kill any stale Git processes, or temporarily disable your IDE’s Git integration to isolate the issue.

How to prevent it

  • Avoid killing Git operations with Ctrl+C — let them finish or use git merge --abort / git rebase --abort to cancel cleanly
  • If you use a Git GUI alongside the terminal, be aware they may run concurrent operations
  • On shared/networked filesystems, avoid having multiple machines operate on the same repo simultaneously
  • Add a pre-commit hook or alias that checks for stale locks before operations
📘