55

I'm getting a strange "cannot lock ref" error when trying to pull changes from github. I've tried git gc, and looked around for similar errors but can't find a solution.

> 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)
k3it
  • 1,621
  • 3
  • 15
  • 18
  • This thread might be also helpful https://stackoverflow.com/questions/22630404/git-push-refs-heads-my-subbranch-exists-cannot-create In case you have an existing branch "a" and you are trying to create something like "a/something-else" – danortDev Jul 11 '19 at 15:56

8 Answers8

99

Your Git is complaining that a reference (rather than a directory) named refs/tags exists. It's not clear what would create that, but see if git rev-parse refs/tags produces a hash ID. If so, that reference needs to go away:

git update-ref -d refs/tags

after which git fetch should work.

If git rev-parse refs/tags fails (which it should—refs/tags itself should not be a valid name) then this is not the problem and it's not clear what the actual problem is.

torek
  • 330,127
  • 43
  • 437
  • 552
  • 1
    that did it! I have no idea how I got into this state. but all is good now. thank you. – k3it Apr 21 '17 at 16:01
  • git fetch had more errors I managed to fix all automatically in my answer below... – Tomer Bar-Shlomo Dec 05 '17 at 10:09
  • 1
    @ZsoltSzilagy: which error? If you have an exact error message, it's often helpful to quote it. The answer here is for the exact error message quoted in the original question—specifically the phrase `'refs/tags' exists; ...`. – torek Jul 15 '19 at 13:36
73

Running

git remote prune origin

Worked for me. Not sure why this was the issue, but seems like there was a broken reference to a remote branch.

Xstatic
  • 953
  • 8
  • 14
  • 1
    This answer should work for most cases where GIT has accumulated references over the period of time on your machine. This removes objects that are no longer being referenced, it does not remove references. Here is a better explanation https://stackoverflow.com/questions/20106712/what-are-the-differences-between-git-remote-prune-git-prune-git-fetch-prune – Jogger Nov 04 '20 at 18:26
  • thankyou,this worked for me! – Aashiq Jan 07 '21 at 11:57
5

error: cannot lock ref 'refs/tags/v2.8': 'refs/tags' exists; cannot create 'refs/tags/v2.8' From github.com:k3it/qsorder

Try deleting your local tag v2.8 and v2.9 then pull again.

$ git tag -d v2.8 
$ git tag -d v2.9

$ git pull

If you want to delete all local tags by a command:

$ git tag | xargs git tag -d
Sajib Khan
  • 18,145
  • 4
  • 50
  • 65
1
#!/usr/bin/env bash
echo "update-ref delete refs/tags"
log="git-update-ref-errors.log"
script="./git-update-ref-exist-tags-delete.sh"
git_command="git update-ref -d refs/tags"

echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors to ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}

echo fetch
log="git-fetch-errors.log"
script="./git-fetch-exist-tags-delete.sh"
git_command="git fetch"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git fetch

echo pull
log="git-pull-errors.log"
script="./git-pull-exist-tags-delete.sh"
git_command="git pull"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git pull

The script above will log errors to XXX-errors.log and fix them by generating and running a XXX-exist-tags-delete.sh automatically from the XXX-errors.log using the following commands:

  1. git update-ref -d refs/tags
  2. git fetch
  3. git pull
1

In my case, the following helped:

git fetch --prune origin
git pull
ellockie
  • 2,136
  • 3
  • 26
  • 30
0

For a quick work around you can use

git push --delete origin 'v2.8'

git push --delete origin 'v2.9'

0

This is what I tried and it worked for me.

git remote prune origin
ascripter
  • 4,220
  • 11
  • 34
  • 50
0

I was trying to push (/dev/somechanges) and I have a remote branch (/dev) with the same prefix when I choose a new name that is not starting with /dev it worked fine.

Melad
  • 1,076
  • 14
  • 16