Do you want to understand what "error: cannot lock ref" in Git actually means and how to fix it?
Version control (VCS) has become a vital part of modern software development workflow. Many VCS system exists, but market research shows that Git is the most popular of all.
Before Git you would copy the entire repository to another directory and then by hand copy your changes to the correct repository. Now creating a branch takes about as long as it takes to type the command. Git scratched many itches, some of which we didn’t even realize until we know it.
Most of the time, Git handles most changes automatically and encourages users to integrate the changes every day or even more often. But sometimes, Git can pops out strange error which is pretty vague and hard to debug if you’re a beginner.
This article is going to show you the reason behind "error: cannot lock ref" in Git and how to fix the error quickly.
Understanding Git locking mechanism
In order to understand why the reason behind "error: cannot lock ref", first, you need to know how Git uses a locking mechanism internally.
Everything related to your working directory is placed in a single, hidden directory named .git
. Inside .git
is all kinds of information about branch, commit, submodule, etc.
A typical .git
directory looks like this
.git/
hooks/
info/
logs/
objects/
refs/
HEAD
config
description
index
packed-refs
Look closer into /refs
and you will see /heads
and /tags
inside. They are the directories that contains information about each of your file in branches and tags.
Whenever you run an operation in Git, it creates index.lock
file inside .git
directory to ensure that no other Git process takes place during the operation.
"error: cannot lock ref" simply means information in /refs
are corrupted and Git cannot continue to create index.lock
file.
What the error looks like
"error: cannot lock ref" comes in many forms, often followed by addition information about what gone wrong. Below is a few of the outputs we’ve seen :
C:\MyWorkStuff\Projects\Ruby\MyProject\>git push origin master
Unable to create branch path https://user:[email protected]/myproject/info/
error: cannot lock existing info/refs
fatal: git-http-push failed
> git pull
error: cannot lock ref 'refs/tags/v2.8': 'refs/tags' exists; cannot create 'refs/tags/v2.8'
From github.com:k3it/qsorder
! [new tag] v2.8 -> v2.8 (unable to update local ref)
error: cannot lock ref 'refs/tags/v2.9': 'refs/tags' exists; cannot create 'refs/tags/v2.9'
! [new tag] v2.9 -> v2.9 (unable to update local ref)
error: cannot lock ref 'refs/remotes/origin/test': is at c21593dc62042d39efc044f366579667e but expected 3d0e5b15fc558cd447fb475a8ecd999
> git pull origin master
From github.com:Microsoft/vscode
* branch master -> FETCH_HEAD
error: cannot lock ref 'refs/remotes/origin/master': is at 2e4bfdb24fd137a1d2e87bd480f283cf7001f19a but expected 70ea06a46fd4b38bdba9ab1d64f3fee0f63806a5
! 70ea06a46f..2e4bfdb24f master -> origin/master (unable to update local ref)
Now let’s go through possible solutions to make the "error: cannot lock ref" goes away.
Quick fix : Remove and re-add remote
As all general computer-related advice said : When in doubt, restart! The quickest way you can get rid of "error: cannot lock ref" is to remove the remote so that you can add it again later.
If you don’t know how to do that, follow step-by-step instructions below.
-
Copy the SSH git URL of your existing remote. You can print it to the terminal using this command:
git remote -v
which will print out something like this:
origin [email protected]:your-username/repo-name.git (fetch)
origin [email protected]:your-username/repo-name.git (push)
-
Remove the remote from your local git repo:
git remote rm origin
-
Add the remote back to your local repo:
git remote add origin [email protected]:your-username/repo-name.git
Prune remote origin
Users across online forums have reported that the command below worked for them:
git remote prune origin
The command will remove references to remote branches in the folder .git/refs/remotes/origin
. So this will not affect your local branches and it will not change anything remote, but it will update the local references you have to remote branches. It seems in some cases these references can contain data Git cannot handle correctly.
If you’re reluctant to try the command above, which I didn’t at first, you can run git remote prune origin --dry-run
to see what happens before proceeding with the actual command.
Clean up and optimize local repository
Git has a built-in gc
command to cleanup unnecessary files and optimize the local repository. The command do housekeeping tasks such as compressing file revisions to improve performance, removing unreachable objects which may have been created from prior invocations of git add, packing refs, pruning reflog, rerere metadata or stale working trees.
Run the following command to optimize your current repository.
git gc --prune=now
If it didn’t work, you can remove .git/logs/refs/remotes/origin/branch
and .git/refs/remotes/origin/branch
then try again, as a few users reported that it works for them.
Double check for confusing branch names
If you’re creating a new branch and none of the above solutions works for you, the next thing you can do is to verify that your existing branch names don’t conflict with the new one. In Git, once a branch named a
already exists, you cannot create a/b
. Likewise, if a/b
exists, creating a/b/c
branch is not possible.
On the one hand, this is great! It got me out of a stuck place.
Wondering if I missed a step, or if this happens to others, though:
On my first `git pull` I got all the remote branches pulled down again, but then this message:
“`
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull
If you wish to set tracking information for this branch you can do so with:
git branch –set-upstream-to=origin/ master
“`
So I ran `git branch –set-upstream-to=origin/master master`
and my next `git pull` got the code changes I was looking for.
Deleting following folders worked for me. Thank you.
.git/logs/refs/remotes/origin/branch
.git/refs/remotes/origin/branch
This worked for me as well. Thanks.
This worked for me too. Thanks.
Fantastic Page Daan, I just had to perform a remote prune origin, which cleared things up nicely.
Many thanks for taking the time to share your knowledge.
Mike