Problem
Windows users can often have this problem
git pull
gives the error: error: cannot lock ref
unable to update local ref
Cause
Cause a) There are multiple branches, whose
names from the beginning up to any slash (or to the end), differ only in upper and lower case.
Branch name clashing (upper/lower case)
#######################################
# Example 1)
#############################
feature/releasecandidate/fix123
feature/releaseCandidate/improveFeature789
------------------------
^
Identical from beginning up to a slash (here the 2nd one)
except for the marked letter, where the upper/lower case differs
# Example 2)
#############################
releaseBranch
releasebranch
-------------
^
Identical from beginning to the end
except for the marked letter
Cause b) Also a problem on linux: One branch is a prefix of another, with a slash boundary:
Prefix with slash-boundary
#######################################
# Example 1) - also a problem on linux
#############################
feature/release2021
feature/release2021/fixIssue07
^
slash boundary
# Example 2)
#############################
feature/release2022
feature/Release2022/fixIssue99
^ ^
differing case slash boundary
(problem on
windows)
Solution
Remove the cause (see exact Cause above).
# inspect your branches, to see if you have the upper/lower case problem
git ls-remote --heads YOUR-GIT-URL
For example: create a branch-naming policy, e.g. all in lower-case letters; or letters before the last slash in lower-case. Or some smart hook, that detect a violation. (but note: In cause a) the problem is only on windows, not on linux).
Background
The problem is that windows stores these branches (from example 1 and 2) in the .git
folder
# inspect the files/folders under
.git/refs/remotes/origin/
and in Cause a) windows cannot distinguish
the differences in upper/lower case, so git on window goes crazy.
In Cause b) you cannot have a folder (e.g. feature/release2021/
) with the same name as a file (feature/release2021
).
Workaround
A short-term workaround that often works (until you've removed the cause) is:
git pack-refs --all
# delete the contents of .git/refs/remotes/origin/*
rm -rf .git/refs/remotes/origin/*
git pull; git pull; git pull # all good? yes!