Quick Summary
- The "cannot lock ref" error shows up when Git tries to update a remote-tracking branch but something is already in the way — usually a stale ref or a naming conflict in your .git folder.
- There are two or three real causes for this and they each need a slightly different fix, so throwing random commands at it usually makes things worse.
- This post walks through the actual commands that clear it up, including the one most Stack Overflow answers skip.
Photo by Oleksandr Chumak on Unsplash
It was a Tuesday afternoon and I was pulling down changes from a feature branch someone else had just pushed. Nothing fancy. Just a regular git fetch. And then this showed up and completely killed my momentum:
I'd seen this error before but never really understood what caused it. I just ran git fetch --prune and hoped for the best. Sometimes it worked. Sometimes it didn't. This time it didn't, and I had to actually sit down and figure out what Git was complaining about. Turns out the cause is almost always one of two things, and once you know what to look for, it's a five-minute fix.
Sound familiar? Yeah. Let me save you the hour of confused Stack Overflow scrolling I did.
What the Error Actually Looks Like
error: cannot lock ref 'refs/remotes/origin/feature/some-branch':
'refs/remotes/origin/feature' exists; cannot create 'refs/remotes/origin/feature/some-branch'
fatal: fetch failed
Or sometimes you get a variation like this:
error: cannot lock ref 'refs/remotes/origin/main':
unable to resolve reference 'refs/remotes/origin/main': reference broken
fatal: fetch failed
The second one is a broken object file situation, which is a bit more annoying. But both are fixable. Don't panic.
Photo by Jake Walker on Unsplash
Why This Happens: The Naming Conflict
Here's the thing Git is trying to tell you. It wants to create a ref at a path like refs/remotes/origin/feature/some-branch, but there's already a file sitting at refs/remotes/origin/feature. Git stores refs as actual files on disk. So if feature already exists as a file, Git can't also make it a directory and put some-branch inside it. Your filesystem doesn't allow a path to be both a file and a folder at the same time. Neither does Git.
This usually happens when someone on your team renamed a branch or deleted an old branch called feature and created a new one called feature/auth or something like that. Your local repo still has the old stale ref sitting there, and now Git is confused.
Why This Happens: The Broken Object File
The second variation — the "reference broken" one — is a different problem. That's usually a corrupt or empty file in your .git/refs folder. It can happen after a bad merge, a hard reset, or honestly sometimes after your laptop just dies mid-operation. I've seen it happen after someone force-pushed to a branch that was being fetched at the same moment. Timing issue. Bad luck.
Either way, the ref file on disk is either empty or contains garbage, and Git refuses to work with it.
Fix 1: Prune the Stale Refs
Start here. This solves the naming conflict case about 80% of the time.
git fetch --prune origin
What --prune does is delete any remote-tracking refs in your local repo that no longer exist on the remote. So if that old origin/feature ref is blocking the new origin/feature/some-branch, pruning clears it out.
If that doesn't work on its own, manually remove the conflicting ref:
git update-ref -d refs/remotes/origin/feature
Then try your fetch again. Honestly, this is the fix in most cases. The update-ref -d command is what most answers skip, and it's the one that actually did it for me.
Fix 2: Delete the Broken Ref File Directly
If you're getting the "reference broken" version and prune didn't help, you need to go in and deal with the file on disk yourself. Yeah, directly editing inside .git. It sounds scarier than it is.
First, figure out which ref is broken:
git fsck --full 2>&1 | grep broken
That'll spit out something like:
broken link from (unknown)
to refs/remotes/origin/some-branch
Now go find that file. From your repo root:
ls -la .git/refs/remotes/origin/
Look for any file that's 0 bytes. That's your culprit. Delete it:
rm .git/refs/remotes/origin/some-branch
Then run:
git fetch origin
Git will re-fetch the ref fresh from the remote and everything should be clean. I was surprised how straightforward this was once I stopped being scared of touching the .git folder.
Fix 3: Pack-Refs as a Last Resort
If you've got a bunch of stale or weird refs and you want to just clean the whole thing up, this command is underused:
git pack-refs --all --prune
What this does is compress all your loose ref files into a single packed-refs file. It's basically housekeeping for your repo's internal reference system. After running it, do a fresh fetch:
git fetch --all --prune
I've used this on repos that had years of branches and thousands of stale refs. It takes a second but it clears up a lot of weirdness. The thing is, most people don't know this command exists. It's not in the "basic Git" tutorials anyone reads.
Fallback: Just Re-Clone
Look, sometimes the local repo is just too far gone. If you've tried all of the above and Git is still complaining, the fastest path forward is:
cd ..
mv my-repo my-repo-backup
git clone git@github.com:yourorg/your-repo.git
Keep the backup for a day, make sure everything's fine, then delete it. Is re-cloning a bit of a nuclear option? Sure. But it's also five minutes versus two hours of debugging a corrupt local state. In my experience, when a repo's .git folder gets truly mangled, you're fighting Git instead of using it. Not worth it.
The "cannot lock ref" error is one of those things that looks terrifying the first time and becomes completely boring once you've seen it a few times. Nine times out of ten it's either a stale ref from a renamed branch or a zero-byte file sitting where Git expects real data. Now you know what to look for instead of just hoping --prune saves you. Sometimes it does. Sometimes you need to go one level deeper. Either way, you've got it handled.
Practical IT troubleshooting, Zoho Workplace guides, health insights, and sports analysis from people who actually care about getting it right. We research, test, and write so you get real answers — not recycled fluff.
๋๊ธ
๋๊ธ ์ฐ๊ธฐ