Case sensitive directory/file names in git

The Context

I was asked for help with someone’s failing tests in their CI. The error they were getting was a no such file or directory error on the line of an import.
They had recently done a refactor which updated a filename from button.tsx to Button.tsx and updated the corresponding imports from import { Button } from './button.tsx'; to import { Button } from './Button.tsx';.
On a local environment, the tests were passing and Git was showing everything was up-to-date with the main branch.

The Problem

Filesystems in UNIX-like systems are usually case-sensitive, meaning you can have both James.txt and JAMES.txt, or a directory called ./james and ./JAMES in the same directory.
MacOS doesn’t work like this - it’s case-insensitive which means you can get something like this:
$ touch file $ ls file $ touch FILE $ ls file # 'FILE' is the same as 'file' so nothing new is created
By default, Git ignores the case of directories and files it tracks → DIRECTORY/FILE.txt is the same as directory/file.txt. So when you make a change of button.tsxButton.tsx git tracks this as the same file and doesn’t track a change, leading to differently named files locally and remotely.
From the git config docs:
Internal variable which enables various workarounds to enable Git to work better on filesystems that are not case sensitive, like APFS, HFS+, FAT, NTFS, etc. For example, if a directory listing finds "makefile" when Git expects "Makefile", Git will assume it is really the same file, and continue to remember it as "Makefile".
The default is false, except git-clone(1) or git-init(1) will probe and set core.ignoreCase true if appropriate when the repository is created.
Git relies on the proper configuration of this variable for your operating and file system. Modifying this value may result in unexpected behavior.


This StackOverflow thread has some discussion on the matter.

Update the global config

You could update the default behaviour of Git to ignore cases, however this is not recommended as it can lead to duplicate files committed to your repo or incorrect conflicts happening later on down the line.
git config --global core.ignorecase false
The setting of core.ignoreCase should match the case-sensitivity of your local file system as it tells Git how to interact with your filesystem. If you are using MacOS or Windows (both case insensitive) ignoreCase should be true (false for Unix).
Run git config --list to see all you current config (or git config --global --list to see your global config).

Use git mv

If it’s just a file rename, you can use git mv to rename it in the filesystem and the Git refs:
git mv -f file FILE # -f required if file already exists
Some people comment that moving via a temporary file (with a completely different name such as file.temp) is required.

Ignore case sensitivity for one commit

git -c "core.ignorecase=false" add .
Here you need to ensure that the original file (with the old case) is removed from git history using git rm.