“error: cannot lock ref” – what to do?

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.

  1. 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)
  1. Remove the remote from your local git repo:

    git remote rm origin

  2. 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.

5 thoughts on ““error: cannot lock ref” – what to do?”

  1. 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.

    Reply
  2. Deleting following folders worked for me. Thank you.
    .git/logs/refs/remotes/origin/branch
    .git/refs/remotes/origin/branch

    Reply
  3. 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

    Reply

Leave a Comment