Git cannot lock ref (tested)
error: cannot lock ref '...' means git could not safely write a ref file (a branch pointer) because something is already in its way. We reproduced the two most common real causes in a throwaway repo: a stale .lock file left over from a crashed git process, and a ref name collision where one branch name is a path prefix of another. The exact wording differs between the two, which is the easiest way to tell them apart.
1. Cause A: a stale .lock file
Git never writes a ref file directly. It writes refs/heads/<branch>.lock, then renames it into place. If git crashes or is killed mid-operation, that .lock file can be left behind, and every future write to that ref fails because the lock file already exists. We reproduced this by creating one by hand:
$ touch .git/refs/heads/master.lock
$ git commit -am "second"
fatal: cannot lock ref 'HEAD': Unable to create '/tmp/gitlockref/.git/refs/heads/master.lock': File exists.
Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.
Exit code 128. Any command that needs to update that specific ref fails the same way. We confirmed it for git branch -d master and git update-ref refs/heads/master HEAD too, both producing the same "cannot lock ref 'refs/heads/master'" message and the same hint text. Commands that don't touch that ref, like git checkout -b newbranch or plain git checkout master (which only moves HEAD, not the master ref itself), succeeded normally even with the stale lock file present.
2. Fix for cause A: delete the lock file
Git's own hint is correct and is the actual fix: find and remove the leftover .lock file, then retry.
$ rm .git/refs/heads/master.lock
$ git commit -am "second"
[master 9b3b911] second
1 file changed, 1 insertion(+)
Exit code 0. If you aren't sure which ref is affected, search for every stale lock at once: find .git -name '*.lock'. Only delete one if you're sure no other git process is actually running against that repo right now — deleting a lock held by a currently running git process can corrupt the ref.
3. Cause B: a ref name collision
Git stores branches as files under .git/refs/heads/, using / in the branch name as a real directory separator. That means a branch named foo and a branch named foo/bar cannot coexist: one needs refs/heads/foo to be a file, the other needs it to be a directory. We reproduced both directions:
$ git branch foo
$ git branch foo/bar
fatal: cannot lock ref 'refs/heads/foo/bar': 'refs/heads/foo' exists; cannot create 'refs/heads/foo/bar'
$ git branch baz/qux
$ git branch baz
fatal: cannot lock ref 'refs/heads/baz': 'refs/heads/baz/qux' exists; cannot create 'refs/heads/baz'
Both fail with exit code 128, and in both cases git checkout -b fails with the identical message instead of creating the branch. Note the wording: it names the other ref as the blocker, not the one you're trying to create, which is the fastest way to tell this apart from the stale-lock case in section 1 — there's no "Another git process seems to be running" hint here at all.
4. Fix for cause B: remove or rename the conflicting ref
There is no way to have both names at once. Delete the one you don't need, or pick a non-conflicting name.
$ git branch -d baz/qux
Deleted branch baz/qux (was 9b3b911).
$ git branch baz
$ echo $?
0
If both branches have commits you need, rename instead of deleting: git branch -m foo foo-old frees up foo for use as a prefix. The same collision rule applies to tags and any other ref under .git/refs/, not just branches.
5. Telling the two causes apart at a glance
| Error text contains | Cause | Fix |
|---|---|---|
| "Unable to create '...lock': File exists" plus "Another git process seems to be running" | Stale .lock file (section 1) | Delete the .lock file (section 2) |
| "'refs/heads/X' exists; cannot create 'refs/heads/Y'" | Ref name collision (section 3) | Delete or rename the conflicting ref (section 4) |
Both are reported as cannot lock ref because both fail at the same point internally — git's ref-locking code refuses to write — but the two root causes and fixes are unrelated. If you hit this while rebasing or merging, the same detection rule applies; also see git detached HEAD if the branch you expected to update doesn't exist at all.
Frequently asked questions
What does "error: cannot lock ref" mean in git?
Git could not write a ref file (usually a branch pointer under .git/refs/) because something was already blocking it: either a leftover .lock file from a previous git process, or another ref whose name collides with the one being created.
How do I know if it's a stale lock file or a name collision?
Read the exact text. A stale lock file error mentions "Unable to create '...lock': File exists" and "Another git process seems to be running". A name collision error instead says "'refs/heads/X' exists; cannot create 'refs/heads/Y'", naming two different ref paths, with no mention of another process.
Is it safe to just delete the .lock file?
Yes, as long as no git process is genuinely running against that repo right now. We confirmed deleting a hand-created stale .lock file immediately let git write the ref again with no side effects. If a real git process is mid-operation, deleting its active lock can corrupt the ref, so check for running git processes first if you're unsure.
Why can't I have a branch called foo and a branch called foo/bar at the same time?
Git stores each branch as a file at .git/refs/heads/<name>, using the OS filesystem, where / is a real directory separator. refs/heads/foo as a file and refs/heads/foo/bar needing refs/heads/foo as a directory are mutually exclusive on disk, so git refuses to create whichever one comes second.
Does this happen with tags too, not just branches?
Yes. Tags live under .git/refs/tags/ using the same file-per-ref layout, so a tag named foo and a tag named foo/bar collide the same way a branch pair does, with the same cannot lock ref error.
Written with AI assistance. Measured on 2026-10-03 with git 2.47.3 on Linux, in a throwaway /tmp repo. Both causes below were reproduced directly: a hand-created stale .lock file, and a real ref-name collision between a branch and a nested branch path. Git is free and open source.