programming Feb 04, 2016

The dangers of HFS+ for git repositories

HFS+ is not case sensitive. It took me 6 months to realize this basic fact. It's one of these things you never bother researching when you consider buying a mac. Last week it hit me hard. I spent 30 minutes trying to fix something that should have been fixed in 30 seconds at most.

A colleague had created File.ext on our website hosted on github pages but printed url/file.ext on important documents they were supposed to hand over to someone. Without access to either Internet or a printer, they asked me to fix this. Easy as pie. Except...

$ mkdir gittest && cd gittest
$ git init
$ touch File && ls
File
$ git add File && git commit -m "add File"
$ mv File file && ls
file
$ git add file && git status
On branch master
nothing to commit, working directory clean

Oops. At this point, I lost quite some trying different ideas. I could not believe HFS+ was case insensitive, it never even occurred to me, I thought git was playing a trick on me. I ended up doing the following:

$ git rm File && git add file
$ git commit -m "rename file"

The problem being fixed, I investigated a bit.

$ touch a A && ls
a
$ echo b > a
$ cat A
b

I then had to get confirmation on the Internet. Of course, most developers already knew about this. I didn't. And I currently have more than 70 repositories in my dedicated folder ~/repositories. Imagine if one of these had file and File in the same directory when I cloned it.

Here is what I finally did to prevent any future headache.

$ du -ch repositories | grep total
14.8G   total
$ hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 20g ~/volume_repos.dmg
created: ~/volume_repos.dmg.sparseimage

I then decided on a mounting point for this volume, added an alias to mount it to my rc file, created a symlink ~/repositories -> ~/mountpointrepo, moved my repos to the volume.

$ mv repositories backup_repositories
$ echo alias mountrepos="hdiutil attach ~/volume_repos.dmg.sparseimage -mountpoint /Users/victor/mountpointrepo" > .zshrc
$ source .zshrc
$ mountrepos
$ ln -s /Users/user/mountpointrepo repositories
$ cp -r backup_repositories/.* backup_repositories/* repositories
$ touch repositories/a repositories/A && ls repositories/
A a

Perfect. And the sparse volume will grow without my intervention to fit my ~/repositories content.

JetBrains IDEs started complaining though:

Filesystem Case-Sensitivity Mismatch The project seems to be located on a case-sensitive file system. This does not match the IDE setting (controlled by property "idea.case.sensitive.fs")

Even if their doc on this subject is very, very poor, I found the following solution:

echo idea.case.sensitive.fs=true >> Library/Preferences/IntelliJIdea15/idea.properties

It feels safer now though I cannot really understand why case insensitive file systems still exist in 2016. Probably because people like me buy macs, I know.

#osx #file systems

Follow me on Twitter, GitHub.

unless otherwise stated, all content & design © copyright 2021 victor felder