Did you know git doesn’t care about case sensitivity? Make sense, it should
treat foobar and FOOBAR as totally different objects. Except when it’s
running on one of the wonderful case-insensitive filesystems like APFS
(Apple File System), which is the default on MacOS.
This can manifest in weird ways. Obviously it will cause issues with files
that are identical except for capitalization, but what about internal git
objects? I found out about this because someone pushed both branch-name and
BRANCH-name to a git server. The error from git was less than clear.
error: cannot lock ref 'refs/remotes/origin/branch-name': Unable to create
'.git/refs/remotes/origin/branch-name.lock': File exists.
Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.
There’s a great StackOverflow answer explaining this in more
detail, but the short version is once my local git binary fetches the ref it
doesn’t see any problem because it’s just reading the branch name from the
packed-ref. Trying to extract it to the filesystem fails though, and manifests
as an Unable to create file error.
This can be “fixed” by converting the refs in the local repo from the
file format to reftable, where the refs are stored in a local binary
format instead of raw filesystem objects. GitLab has a great
blog describing this feature in more detail.
$ git refs migrate --ref-format=reftable
error: migrating repositories with worktrees is not supported yet
Guess I’ll have to wait a while for this feature to be more mature though.
In the meantime:
- (if possible) APFS supports case sensitivity, but changing this requires reformatting the filesystem.
- I can’t easily do this on my work machine due to external controls, but this is the best fix if you can.
- Add a pre-receive hook to block case-insensitive filenames
- Most git servers support regex matching, but matching against already exisiting branches is harder
- This would only catch one type of errors, and I suspect there’s several others :(
- Also would allow new branches to be pushed but it’s still possible for a user to have an old local tracking branch ref that would conflict
- Ask politely for devs to not push conflicting branch names
- good luck :)
- Be aware of case issues and nuke remote branches if it becomes a problem