This Git error occurs when trying to rename a file where only the case differs (e.g., 'File.txt' to 'file.txt') on Windows or macOS. These operating systems use case-insensitive filesystems by default, which cannot distinguish between files that differ only in case.
This error occurs when Git attempts to rename a file on a case-insensitive filesystem (Windows NTFS or macOS APFS/HFS+) where the only difference between the old and new filename is the letter casing. For example, renaming `File.txt` to `file.txt` or `README.md` to `Readme.md`. On case-insensitive filesystems, the operating system treats `File.txt` and `file.txt` as the same file. When Git tries to perform a direct rename, the filesystem rejects it with "Invalid argument" because from its perspective, you're trying to rename a file to its current name. This is a fundamental difference between how Git (which is case-sensitive) and Windows/macOS filesystems (which are case-insensitive by default) handle filenames: - **Git**: Tracks `File.txt` and `file.txt` as completely different files - **Windows/macOS**: Sees them as the same file, just with different display capitalization - **Linux**: Case-sensitive, so `File.txt` and `file.txt` are distinct files This mismatch causes problems when: 1. You try to rename a file to change only its case 2. You pull changes from a repository where someone on Linux renamed a file's case 3. You're trying to match a naming convention (e.g., all lowercase)
The most reliable solution is to rename the file in two steps, using a temporary intermediate name:
# Step 1: Rename to a temporary name
git mv File.txt file-temp.txt
# Step 2: Rename from temporary to final name
git mv file-temp.txt file.txt
# Step 3: Commit the change
git commit -m "Rename File.txt to file.txt (case change)"This works because:
1. File.txt to file-temp.txt is a clear rename (different name)
2. file-temp.txt to file.txt is also a clear rename
3. Git tracks both renames and the end result is the case change you wanted
For multiple files:
# Rename all .TXT files to .txt
for f in *.TXT; do
temp="${f%.TXT}-temp.txt"
final="${f%.TXT}.txt"
git mv "$f" "$temp"
git mv "$temp" "$final"
done
git commit -m "Normalize file extensions to lowercase"In some Git versions, you can force the rename using the -f or --force flag:
# Force the case-only rename
git mv -f File.txt file.txt
# Commit the change
git commit -m "Rename File.txt to file.txt"Note: This may not work on all Git versions or filesystem configurations. If it fails, use the two-step rename method instead.
Check your Git version:
git --versionThe -f flag is more likely to work on Git 2.0.1 and later, but filesystem behavior still varies.
An alternative approach is to remove the file from Git's index and re-add it with the new name:
# Remove the old filename from Git's index (not from disk)
git rm --cached File.txt
# Rename the actual file (use your OS file manager or command)
# On Windows:
ren File.txt file.txt
# On macOS/Linux:
mv File.txt file.txt
# Add the file with the new name
git add file.txt
# Commit
git commit -m "Rename File.txt to file.txt"Important: The --cached flag removes the file from Git's tracking only, not from your working directory.
If the filesystem won't let you rename directly:
# Remove from index
git rm --cached File.txt
# Rename via temporary file
mv File.txt temp-file.txt
mv temp-file.txt file.txt
# Add back
git add file.txt
# Commit
git commit -m "Change file case"Git has a configuration option core.ignoreCase that controls how it handles case differences:
# Check current setting
git config --get core.ignorecase
# On Windows/macOS, this is typically 'true' by defaultTemporarily disable ignoreCase for the rename:
# Set to false temporarily
git config core.ignorecase false
# Now try the rename
git mv File.txt file.txt
# Restore the setting
git config core.ignorecase true
# Commit
git commit -m "Rename file with case change"Warning: Setting core.ignorecase to false permanently on a case-insensitive filesystem can cause other issues, such as:
- Git may see the same file twice (as both File.txt and file.txt)
- Status commands may show phantom changes
- Merge operations may behave unexpectedly
Only use this setting change temporarily for the specific rename operation.
If you have access to a Linux system (including WSL on Windows or Docker), you can perform the rename there where the filesystem is case-sensitive:
Using WSL (Windows Subsystem for Linux):
# Open WSL terminal
wsl
# Navigate to your repository
cd /mnt/c/path/to/your/repo
# Perform the rename directly
git mv File.txt file.txt
# Commit
git commit -m "Rename File.txt to file.txt"
# Exit WSL
exitUsing Docker:
# Run a Git container with your repo mounted
docker run -it --rm -v "$(pwd):/repo" -w /repo alpine/git sh
# Inside the container, perform the rename
git mv File.txt file.txt
git commit -m "Rename File.txt to file.txt"
# Exit the container
exitUsing a Linux VM or remote server:
# SSH to your Linux server
ssh user@linux-server
# Clone or access the repository
cd /path/to/repo
# Perform the rename
git mv File.txt file.txt
git commit -m "Rename File.txt to file.txt"
git push
# Back on Windows/macOS, pull the changes
git pullThis method is especially useful for batch renaming multiple files.
If you encounter this error when pulling changes from a remote (someone else renamed a file's case), follow these steps:
# First, stash any local changes
git stash
# Fetch the latest changes
git fetch origin
# Check what files are affected
git diff --name-only HEAD origin/main
# If there are case conflicts, remove the local file from index
git rm --cached File.txt
# Reset to the remote state
git reset --hard origin/main
# Or, if you need to preserve local changes:
git checkout --theirs File.txt
git add file.txtPrevent future issues with .gitattributes:
# Create or update .gitattributes
echo "* text=auto" >> .gitattributes
git add .gitattributes
git commit -m "Add .gitattributes for consistent handling"Check for duplicate files (different cases in the repo):
# List all tracked files, sort case-insensitively, find duplicates
git ls-files | sort -f | uniq -diIf duplicates exist in the remote repository, the Linux user who created them needs to resolve it.
For projects that need to normalize many filenames (e.g., all lowercase), use a script:
Bash script for renaming (use in Git Bash on Windows or Linux/macOS):
#!/bin/bash
# rename-to-lowercase.sh
# Find all files and rename to lowercase
git ls-files | while read file; do
dir=$(dirname "$file")
base=$(basename "$file")
lower=$(echo "$base" | tr '[:upper:]' '[:lower:]')
if [ "$base" != "$lower" ]; then
echo "Renaming: $file -> $dir/$lower"
git mv "$file" "$dir/temp-$base"
git mv "$dir/temp-$base" "$dir/$lower"
fi
done
git commit -m "Normalize all filenames to lowercase"PowerShell script for Windows:
# Get all tracked files
$files = git ls-files
foreach ($file in $files) {
$dir = Split-Path $file -Parent
$name = Split-Path $file -Leaf
$lower = $name.ToLower()
if ($name -cne $lower) {
$temp = if ($dir) { "$dir/temp-$name" } else { "temp-$name" }
$final = if ($dir) { "$dir/$lower" } else { $lower }
Write-Host "Renaming: $file -> $final"
git mv $file $temp
git mv $temp $final
}
}
git commit -m "Normalize all filenames to lowercase"Using `git filter-repo` for historical rewrites (advanced):
# Install git-filter-repo first
pip install git-filter-repo
# Rename all paths to lowercase throughout history
git filter-repo --path-rename 'File.txt:file.txt'Warning: Rewriting history affects all collaborators and requires force push.
### Understanding Filesystem Case Sensitivity
Different operating systems and filesystems handle case differently:
| OS/Filesystem | Case Behavior | Default |
|---------------|---------------|---------|
| Windows NTFS | Case-preserving but case-insensitive | Yes |
| macOS APFS | Case-insensitive by default, can be case-sensitive | CI by default |
| macOS HFS+ | Case-insensitive by default | CI by default |
| Linux ext4 | Case-sensitive | Yes |
| Linux on WSL2 | Case-sensitive (in Linux filesystem) | Yes |
Case-preserving vs case-insensitive:
- Case-preserving: The filesystem remembers that you created File.txt with capital F
- Case-insensitive: But when you access file.txt, it finds File.txt
### Git's core.ignoreCase Setting
Git auto-detects the filesystem's case sensitivity during git init or git clone:
# Check the setting
git config --get core.ignorecase
# true = case-insensitive filesystem (Windows/macOS default)
# false = case-sensitive filesystem (Linux default)When core.ignorecase=true:
- Git treats File.txt and file.txt as the same
- Renames that only change case are problematic
- This matches the underlying filesystem behavior
### The "Two Files With Same Name" Problem
If a Linux user creates two files that differ only in case:
project/
README.md
readme.md # Different file on Linux!When cloned on Windows/macOS:
- Only one file will exist in the working directory
- Git will be confused about which version is checked out
- Status may show the file as modified even when unchanged
Resolution:
# On Linux, remove one of the files
git rm readme.md # Keep README.md
git commit -m "Remove case-duplicate file"### Creating a Case-Sensitive Disk Image (macOS)
For development work that needs case sensitivity on macOS:
# Create a case-sensitive APFS volume
diskutil apfs addVolume disk1 'Case-sensitive APFS' CaseSensitive
# Or create a sparse disk image
hdiutil create -size 10g -fs 'Case-sensitive APFS' -volname 'CaseSensitive' ~/CaseSensitive.sparseimage
# Mount it
hdiutil attach ~/CaseSensitive.sparseimage
# Clone your repo there
cd /Volumes/CaseSensitive
git clone your-repo### WSL2 and Case Sensitivity
Windows Subsystem for Linux provides a case-sensitive environment:
# Files stored in the Linux filesystem (/home/user/...) are case-sensitive
# Files accessed via /mnt/c/... are still case-insensitive (Windows filesystem)
# For case-sensitive work, clone repositories inside WSL's filesystem:
cd ~
git clone https://github.com/user/repo.git
# Not in /mnt/c/Users/...### Preventing Case Issues in Teams
Establish naming conventions:
# .editorconfig
[*]
# Use lowercase for all files
filename_casing = lowercaseAdd pre-commit hook to check for case issues:
#!/bin/bash
# .git/hooks/pre-commit
# Check for files that would conflict on case-insensitive systems
duplicates=$(git ls-files | sort -f | uniq -di)
if [ -n "$duplicates" ]; then
echo "Error: Case-conflicting files detected:"
echo "$duplicates"
exit 1
fiUse CI to catch case conflicts:
# .github/workflows/check-case.yml
name: Check Case Conflicts
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for case conflicts
run: |
duplicates=$(git ls-files | sort -f | uniq -di)
if [ -n "$duplicates" ]; then
echo "Case-conflicting files found:"
echo "$duplicates"
exit 1
fi### Related Git Configuration
# Other case-related settings to be aware of:
# How Git handles Unicode normalization (similar to case issues)
git config core.precomposeUnicode true # macOS specific
# Check attributes for specific files
git check-attr -a filenamekex_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