Git warns that file paths have collided due to a case-sensitive rename on a case-insensitive filesystem. This happens when a repository contains files that differ only in letter case (like README.md and readme.md), which macOS APFS or HFS+ cannot store separately. Fix by renaming files in the repository or using a case-sensitive disk image.
This warning occurs when Git encounters file paths that differ only in letter caseβsuch as `File.txt` and `file.txt`βwhile operating on a case-insensitive filesystem. macOS uses APFS (Apple File System) or HFS+ by default, both of which are case-insensitive but case-preserving. This means while the filesystem remembers that you named a file "README.md", it considers "readme.md", "Readme.MD", and "README.MD" to be the same file. When you clone or check out a repository that was created on a case-sensitive filesystem (like Linux ext4), it may contain multiple files that differ only in case. On macOS, Git cannot create both files because the filesystem treats them as identical. Instead of failing silently or overwriting one file, Git warns you about the collision. The warning message specifically mentions: - **"paths have collided"** - Two or more files in the repository have paths that the filesystem considers identical - **"case-sensitive rename"** - A file was renamed with only case differences (e.g., `config.js` to `Config.js`) - **"case-insensitive filesystem"** - Your filesystem cannot distinguish between paths that differ only in letter case This is a common issue when: 1. Collaborating across Linux (case-sensitive) and macOS (case-insensitive) systems 2. Cloning repositories created on Linux servers 3. Working with projects that rely on case-sensitive imports (common in JavaScript/TypeScript)
First, determine exactly which files have conflicting names. Git shows this in the warning, but you can also investigate:
# List all files tracked by Git (case-sensitive listing)
git ls-tree -r HEAD --name-only | sort > /tmp/git-files.txt
# Find potential case collisions
git ls-tree -r HEAD --name-only | tr '[:upper:]' '[:lower:]' | sort | uniq -d
# For a more detailed view, compare lowercase versions
git ls-tree -r HEAD --name-only | while read f; do
echo "$(echo "$f" | tr '[:upper:]' '[:lower:]') -> $f"
done | sort | uniq -D -f1Alternative using awk:
git ls-tree -r HEAD --name-only | awk '{
lower = tolower($0)
if (seen[lower]) {
print "COLLISION: " seen[lower] " vs " $0
}
seen[lower] = $0
}'This identifies all file pairs that differ only in case.
The best long-term solution is to rename files in the repository so there are no case collisions. This must be done on a case-sensitive system or using Git's index directly:
Method 1: Using git mv with --force (on macOS):
# Git's mv command can handle case renames on case-insensitive systems
# This two-step process ensures Git tracks the rename properly
# Example: rename Utils.js to utils.js
git mv Utils.js utils-temp.js
git mv utils-temp.js utils.js
git commit -m "fix: rename Utils.js to utils.js for case-insensitive filesystems"Method 2: Using git rm --cached:
# Remove the file from Git's index (not from disk)
git rm --cached Utils.js
# Add the correctly-cased version
git add utils.js
git commit -m "fix: standardize file casing for cross-platform compatibility"Method 3: On a case-sensitive system (Linux or case-sensitive volume):
# If you have access to Linux or a case-sensitive disk image
mv Utils.js utils.js
git add -A
git commit -m "fix: rename Utils.js to utils.js"After fixing, push the changes so all collaborators get the corrected file names.
If you frequently work with repositories that require case sensitivity, create a dedicated case-sensitive APFS volume:
Using Disk Utility (GUI):
1. Open Disk Utility (Applications > Utilities)
2. Select your main drive in the sidebar
3. Click + to add a volume (or Partition if using HFS+)
4. Set the format to APFS (Case-sensitive)
5. Name it something like "Development"
6. Click Add
Using Terminal:
# Create a 50GB case-sensitive APFS volume
# Replace "disk1" with your actual disk identifier (use 'diskutil list' to find it)
sudo diskutil apfs addVolume disk1 "Case-sensitive APFS" Development
# Or create a fixed-size volume
sudo diskutil apfs addVolume disk1 "Case-sensitive APFS" Development -quota 50gClone repositories to the case-sensitive volume:
# The new volume mounts at /Volumes/Development
cd /Volumes/Development
git clone https://github.com/user/repo.git
# Or move your existing project
mv ~/Projects/problematic-repo /Volumes/Development/This approach gives you true case sensitivity without affecting your main system.
For quick fixes or occasional case-sensitive work, a sparse disk image is lighter than a dedicated volume:
# Create a 10GB sparse case-sensitive disk image
hdiutil create -size 10g -type SPARSE -fs "Case-sensitive APFS" -volname CaseSensitive ~/CaseSensitive.sparseimage
# Mount the disk image
hdiutil attach ~/CaseSensitive.sparseimage
# Now /Volumes/CaseSensitive is case-sensitive
cd /Volumes/CaseSensitive
git clone https://github.com/user/repo.git
# When done, unmount
hdiutil detach /Volumes/CaseSensitiveAuto-mount on login (optional):
# Add to your shell profile (~/.zshrc or ~/.bash_profile)
hdiutil attach ~/CaseSensitive.sparseimage -quiet 2>/dev/null || trueThe sparse image only uses disk space for actual content, not the full allocated size.
Configure Git to help prevent case collision issues before they become problems:
# Enable case-sensitive checking (warns when adding files that differ only in case)
git config --global core.ignorecase false
# Note: This doesn't make your filesystem case-sensitive, but Git will:
# - Track files with their original case
# - Warn about potential issues
# - Be more strict about path matchingCheck current setting:
git config --get core.ignorecase
# Returns "true" by default on macOS, "false" on LinuxFor a specific repository:
cd /path/to/repo
git config core.ignorecase falseImportant: Setting core.ignorecase false on a case-insensitive filesystem can lead to unexpected behavior. Git may show files as modified when they're not, or fail to detect actual changes. Use this setting primarily on case-sensitive volumes.
If you encounter this warning during a merge, rebase, or pull, you need to decide which version of the colliding files to keep:
# If you're in the middle of a merge
# First, see what's happening
git status
# List the colliding files from the merge
git diff --name-only --diff-filter=U
# Option 1: Keep the version from your branch
git checkout --ours path/to/File.js
git add path/to/File.js
# Option 2: Keep the version from the other branch
git checkout --theirs path/to/file.js
git add path/to/file.js
# Option 3: Keep only one, delete the other from Git
git rm --cached path/to/Utils.js # Remove the unwanted casing
git add path/to/utils.js # Keep this versionIf the merge is complete but files are wrong:
# See which file actually exists on disk
ls -la path/to/
# Reset the problematic file to the correct version
git checkout HEAD -- path/to/utils.js
# Or from a specific commit
git checkout <commit-hash> -- path/to/utils.jsAfter resolving, commit the merge or continue the rebase.
Prevent case collisions from entering your repository by adding a pre-commit hook:
# Create or edit .git/hooks/pre-commit
cat << 'EOF' > .git/hooks/pre-commit
#!/bin/bash
# Check for case-insensitive filename collisions
collisions=$(git diff --cached --name-only --diff-filter=ACR | \
tr '[:upper:]' '[:lower:]' | \
sort | \
uniq -d)
if [ -n "$collisions" ]; then
echo "ERROR: Case-insensitive filename collision detected!"
echo "The following filenames differ only in case:"
echo "$collisions"
echo ""
echo "This will cause issues on case-insensitive filesystems (macOS, Windows)."
echo "Please rename files to avoid collisions."
exit 1
fi
EOF
chmod +x .git/hooks/pre-commitFor team-wide enforcement, use a shared hook with Husky (Node.js projects):
npm install husky --save-dev
npx husky install
npx husky add .husky/pre-commit "scripts/check-case-collisions.sh"Create scripts/check-case-collisions.sh with the same logic as above.
This prevents new case collisions from being committed, protecting macOS and Windows users on your team.
### Understanding Case Sensitivity on macOS
macOS supports multiple filesystem configurations:
| Filesystem | Case Behavior | Default on macOS |
|------------|---------------|------------------|
| APFS | Case-insensitive, case-preserving | Yes (default) |
| APFS (Case-sensitive) | Fully case-sensitive | No |
| HFS+ | Case-insensitive, case-preserving | Legacy default |
| HFS+ (Case-sensitive) | Fully case-sensitive | No |
Case-preserving means the system remembers that you named a file "README.md" and displays it that way, but treats "readme.md" as the same file.
Why Apple chose case-insensitivity: Many macOS applications historically assumed case-insensitivity. Making APFS case-sensitive by default would break these apps. Apple provides case-sensitive volumes as an option for developers who need it.
### Git's core.ignorecase Setting
Git has a core.ignorecase configuration that affects how it handles case:
# Check the setting
git config core.ignorecase
# On macOS, Git auto-detects and sets this to "true"
# On Linux, it's typically "false"When `core.ignorecase=true`:
- Git treats File.txt and file.txt as the same file
- Renaming with only case changes may not be tracked properly
- This matches the filesystem's behavior on macOS
When `core.ignorecase=false`:
- Git tracks files with exact case sensitivity
- May show phantom modifications on case-insensitive filesystems
- Can lead to "both modified" conflicts during merges
### Checking if Your Volume is Case-Sensitive
# Check filesystem format
diskutil info / | grep "Type (Bundle)"
# "apfs" = standard APFS (case-insensitive)
# "apfs (case-sensitive)" = case-sensitive APFS
# Quick test
touch /tmp/CaseTest /tmp/casetest 2>/dev/null
if [ -f /tmp/CaseTest ] && [ -f /tmp/casetest ]; then
ls /tmp/CaseTest /tmp/casetest 2>/dev/null | wc -l | grep -q 2 && \
echo "Case-sensitive" || echo "Case-insensitive"
fi
rm -f /tmp/CaseTest /tmp/casetest 2>/dev/null### Cross-Platform Project Best Practices
When working on projects shared between Linux and macOS:
1. Establish naming conventions: Use consistent casing (e.g., all lowercase for directories, PascalCase for React components)
2. Add CI checks:
# .github/workflows/check-case.yml
- name: Check for case collisions
run: |
COLLISIONS=$(git ls-tree -r HEAD --name-only | tr '[:upper:]' '[:lower:]' | sort | uniq -d)
if [ -n "$COLLISIONS" ]; then
echo "Case collision detected: $COLLISIONS"
exit 1
fi3. Use .gitattributes for consistency:
# .gitattributes
* text=auto4. Document in README: Note if the project requires case-sensitive filesystem
### Docker and Case Sensitivity
Docker containers typically run Linux (case-sensitive), but Docker Desktop on macOS mounts your local filesystem:
# Inside Docker container on macOS, /workspace is still case-insensitive
# if mounted from your Mac filesystem
# Solution: Use a Docker volume instead of a bind mount
docker volume create my-project
docker run -v my-project:/workspace -it ubuntu bash
# /workspace inside container is now case-sensitive (Linux ext4)### Recovering from Collision During Clone
If git clone produces the warning:
# Clone completed but with warnings
# Check what files actually exist
ls -la
# See what Git thinks should be there
git ls-tree HEAD --name-only
# Reset to a clean state (one file will be chosen)
git checkout -- .
# Find which version you got
git statusThe file that "wins" depends on checkout order and filesystem behavior. To get a specific version:
# Checkout the specific file you want
git show HEAD:path/to/Utils.js > utils.js
# Now you have the content, even if named differently### When You Actually Need Case Sensitivity
Some projects genuinely require case sensitivity:
- Go projects: Package naming conventions use case
- Some JavaScript imports: import Header from './Header' vs './header'
- Internationalization files: en-US.json vs en-us.json
- Test fixtures: Testing case-sensitive behavior
For these, use a case-sensitive APFS volume or develop in a Linux VM/container.
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git