Dave L.
Dave L.

Reputation: 9801

Git on MacOS case sensitivity: cannot lock ref

I believe a teammate had a feature branch named Fix/my-fix and then renamed it fix/my-fix, changing the case, and pushed it to our central repo.

Now, every time I do a git pull, I see

error: cannot lock ref 'refs/remotes/origin/fix/my-fix': is at addd9e22effc39t86eca875a1db74f4cc2d09747 but expected cec2dce30eb3a5tf370c3d3b39540f9d2e347020
 ! cec2dce30..addd9e22e  fix/my-fix                 -> origin/fix/my-fix  (unable to update local ref)

If I do a git remote prune origin or git fetch --all --prune, then it fixes the issue so I can do one successful pull but then the second time I pull I get the error again. So essentially I have to prune before every pull.

Is there any way I can solve this issue locally, without deleting his feature branches from our central git repo? I don't care about his branch at all, so an acceptable workaround would be to tell git to ignore it permanently somehow; I just need to be able to consistently pull without having to prune.

I've also tried

git update-ref -d refs/remotes/origin/fix/my-fix

and

git gc --prune=now

and those similarly only solved the issue temporarily.

I've read the background around case-sensitive filesystems in this article.

Upvotes: 1

Views: 1413

Answers (2)

abligh
abligh

Reputation: 25169

Laziness >> Correctness here. Assuming the server now only has one case variant:

  • Push your local branches.
  • Blow away your repo (I suggest just renaming the directory so you can recover)
  • Start again with a new git clone

If you don't want to push everything to the server, you can push to a local bare repository with git init --bare.

Upvotes: 1

torek
torek

Reputation: 489293

Based on your description, the uppercase spelling version of the branch should not be returning (so that the one-time git fetch -p or git remote prune should have been a permanent solution). However, if it works once, you can just enable it as the default action for this one repository on your Mac:

git config fetch.prune true

or for all of your repositories1 on your Mac:

git config --global fetch.prune true

This is equivalent to making all git fetch commands be git fetch -p commands.

(There's no particularly good reason not to run with fetch.prune set to true. I do this myself: I have my global configuration set this way.)


1Technically, this would be all repositories except any that locally override with fetch.prune=false. In general—there are some specific and important exceptions—things that you set with git config --global get overridden by anything you set with git config, because what Git does is:

  • Read the system configuration file first, to get settings.
  • Read your global configuration file for settings. Anything you set here that was already set is now overridden by your global setting.
  • Read your repository's configuration file for settings. Anything you set here that was already set is now overridden by the repository's setting.
  • Apply any -c key=value arguments from the command line. Anything you set here that was already set is now overridden by the command-line setting.

This is particularly useful if you, e.g., do consulting work: you can set your name and email address to your personal settings, then, for each repository on which you're doing consulting work, set your name and email address to whatever the job requires for that repository.

Upvotes: 2

Related Questions