Reputation: 29439
I get the following error from git when trying to pull (or checkout or cherry-pick) a commit involving files whose filename has changed only in terms of upper vs. lower case:
The following untracked working tree files would be overwritten by merge
after which it lists all the files with only case differences. A git status
shows nothing in my working directory.
I was able to perform the pull
successfully after first deleting the local copy of the files in question, but I was wondering if there was a more elegant way to work around, or better yet, avoid the problem in the first place. Other users running on MacOS with the same repository on their local machines had no such symptoms/problem.
Upvotes: 6
Views: 855
Reputation: 6102
The git
utility assumes your filesystem is case-sensitive because most, if not all, Linux and FreeBSD filesystems are so.
But on macOS, by default the file system is case-insensitive. This mismatch can result in the problems you are seeing.
If case-sensitivity is not required by the project/code, you can use this answer.
If case-sensitivity is required, and you are operating on macOS with a case-insensitive file system, you can make a new virtual case-sensitive volume sharing the same APFS partition as your other volumes.
You would use the new case-sensitive volume exclusively for your git repo work. If you compile an application on this volume, you can test it with configuration and data files on your other case-insensitive volumes if required.
Open Disk Utility and click the +
button for a new Volume:
Name the new Volume:
Store your files in this directory:
% ls -ld /Volumes/GitRepo
drwxr-xr-x 5 risner staff 160 Dec 15 21:25 /Volumes/GitRepo
Upvotes: 3
Reputation: 7507
Having trouble with case-sensitive file/directory renames in a git repo on a case-insensitive FS/OS; Follow these 3 steps:
git config --global core.ignorecase
returns nothing, or at the very least true
. If false
- reset to null, so git can autodetect this configuration according to the filesystem a repo is cloned onto.git config core.ignorecase
is set to true
. If none or false - set to true.Git was built on, and therefore most compatible with, case-sensitive filesystems. As git became more popular its application on case-insensitive filesystems increased, and so did the amount of issues found and bugs opened for case handling incompatibilities. Don't get me wrong - these issues were (and if still open - are being) addressed, but still a rocky road.
I cannot recommend formatting an entire filesystem to be case-sensitive as a resolution, as it may break other applications which expect filenames to be case-agnostic. True story.
This is just my personal opinion, but I feel like things have drastically shifted for git enthusiasts in the past 15 years, from requiring a case-sensitive formatted FS, to better (and almost seamless) handling of case-insensitivities by git itself.
An ad-hoc method can be employed to resolve a specific file-rename causing problems, but that is a workaround - not a solution. Git should be able to handle insensitive filesystems "out-of-the-box":
core.ignoreCase
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.
Git should be able to handle file/directory letter-case-renames automatically when cloning or initializing a repository on an insensitive environment. There will be problems, of course, if the repository contains two paths that should coexist, and differ only in letter-case (e.g. mypath/myfile.txt
and mypath/MyFile.txt
) - this is not possible on an insensitive filesystem. Another reason for trouble is if the repository was first cloned/initialized on a case-sensitive FS, but later physically moved (mv
/cp
) to an insensitive one; in such case setting the repository's core.ignorecase
config to true should make things better.
Still, while git "should" be able to handle such cases, it is important to keep git up-to-date. As issues are discovered, newer versions have them resolved, making for a much smoother experience. I'm posting some examples from the release notes; These are NOT to be regarded as a "shame list" in any way, but rather to show the engagement of the maintainers and the goals they achieved towards seamless support for case-insensitive FS/OS. And to convince the ones who managed to read so far of the importance of software updates:
Upvotes: 2
Reputation: 52226
"Other uses running on MacOS with the same repository on their local machines had no such symptoms/problem."
On case insensitive file systems: the names of the files on a user's disk keep a trace of the sequence of actions that happened on that user machine. Once a file is created on disk (either because a git swicth
or git pull
created on disk a new file with the casing listed in git, or because the user named the file himself) it will retain that casing.
To illustrate this : on Windows and MacOS, mv Readme.md README.md
is a no-op -- even if the file is actually named rEaDmE.md
, it will keep its initial name.
In a similar way: if you switch between branches where a specific file is named either Readme.md
or README.md
, the name of the file on your disk will actually not change -- it will keep the name it initially had.
So you may end up with a repo on your disk where files have not the same names as on your colleague's disk, just because you happened to git pull
the feature-xyz
branch before switching to master
.
To spot discrepancies between your files on disk and the names in git, you can compare git ls-files
with git ls-files | xargs ls
:
diff <(git ls-files) <(git ls-files | xargs ls)
(note: I don't have a MacOS filesystem at hand, I hope ls readme.md
will output README.md
if the file on disk is actually in uppercase, and that git ls-files | xargs ls
will show the actual case of your names on your filesystem rather than just repeating the output of git ls-files
)
A common workaround to rename files on Windows/MacOS is to use a temporary name :
mv Readme.md tmp-name && mv tmp-name README.md
Same thing goes for git mv
: git mv Readme.md README.md
will succesfully change the name stored in git but not the name on disk.
You can :
git mv Readme.md tmp-name && git mv tmp-name README.md
If your intention is to have your files on disk match the names in git, you may use the output of the first command to issue renaming commands.
Upvotes: 1
Reputation: 1329752
Deleting the local file (as in here) is one solution.
Check first if a git config --global core.ignoreCase true
could help on your next git pull
.
Check if other users have already set that setting.
Upvotes: 1