This error occurs when Git tries to access files that have been offloaded to iCloud by macOS's 'Optimize Mac Storage' feature. The files exist as placeholder stubs locally, and Git cannot read their actual contents, causing operations like status, diff, or commit to fail.
This error indicates that Git is attempting to read a file that has been "evicted" from local storage by iCloud Drive. When macOS's "Optimize Mac Storage" feature is enabled, iCloud automatically removes local copies of files that haven't been accessed recently, replacing them with lightweight placeholder files (named like `.original_filename.icloud`). The actual file contents remain in iCloud and are downloaded on-demand when accessed through Finder. The problem is that Git doesn't trigger the automatic download mechanism that Finder uses. Instead, Git encounters the placeholder file and fails to parse it as valid content. This breaks various Git operations including `git status`, `git diff`, `git add`, and `git commit`. Apple explicitly advises against storing "app folders, libraries, or .tmp files in iCloud Drive," and Git's `.git` directory qualifies as an application folder. The internal structure of a Git repository relies on specific file formats and naming conventions that iCloud's syncing and eviction behaviors can corrupt or break. This issue is particularly common when: - Repositories are stored in iCloud-synced folders (Desktop, Documents with iCloud sync enabled) - The repository hasn't been accessed for a while and macOS decided to free up space - Working on a new Mac where iCloud is still downloading files - The `Optimize Mac Storage` option is enabled in iCloud settings
The quickest fix is to force iCloud to download all evicted files in your repository using the brctl command:
Download all files in the repository:
# Navigate to your repository
cd /path/to/your/repo
# Download all evicted files recursively
find . -type f -exec brctl download {} \;Download only .icloud placeholder files:
# Find and download only evicted files (those with .icloud extension)
find . -name '.*icloud' | perl -pe 's|(.*)/.(.*).icloud|$1/$2|s' | while read file; do brctl download "$file"; doneMonitor download progress:
# Watch iCloud download activity
brctl log -w -tAlternative using fileproviderctl (macOS Ventura+):
# Materialize files (download them locally)
find . -type f -exec fileproviderctl materialize {} \;Note that brctl download is asynchronous - it queues the download but doesn't wait for completion. Large repositories may take time to fully download.
The most critical files to download are within the .git directory, as these contain Git's internal data:
Download all .git contents:
cd /path/to/your/repo
# Download everything in .git
find .git -type f -exec brctl download {} \;Download Git objects specifically:
# These are the most commonly evicted and problematic
find .git/objects -type f -exec brctl download {} \;Download refs and HEAD:
find .git/refs -type f -exec brctl download {} \;
brctl download .git/HEAD
brctl download .git/indexCheck for .icloud placeholders in .git:
# List any evicted files in .git directory
find .git -name '*.icloud' -o -name '.*icloud'After downloading, verify Git works:
git status
git log --oneline -5Prevent future evictions by disabling the optimize storage feature:
On macOS Ventura and later:
1. Open System Settings
2. Click your Apple ID (top of sidebar)
3. Click iCloud
4. Click iCloud Drive
5. Turn OFF Optimize Mac Storage
On macOS Monterey and earlier:
1. Open System Preferences
2. Click Apple ID
3. Select iCloud from the sidebar
4. Click Options next to iCloud Drive
5. Uncheck Optimize Mac Storage
What this does:
- All iCloud Drive files will be downloaded and kept locally
- Files will no longer be automatically evicted
- Uses more local disk space but prevents Git issues
Verify the setting took effect:
# Check iCloud Drive status
brctl status
# List any remaining evicted files
find ~/Library/Mobile\ Documents -name '*.icloud'Note: This downloads ALL iCloud Drive content, which may take significant time and disk space.
The recommended long-term solution is to keep Git repositories outside of iCloud-synced folders:
Create a development directory:
# Create a local-only development folder
mkdir -p ~/dev
# Or use another non-synced location
mkdir -p ~/code
mkdir -p ~/projectsMove your repository:
# First, ensure all files are downloaded
cd ~/Library/Mobile\ Documents/com~apple~CloudDocs/your-repo
find . -type f -exec brctl download {} \;
# Wait for downloads to complete, then move
mv ~/Library/Mobile\ Documents/com~apple~CloudDocs/your-repo ~/dev/your-repo
# Or if it's in Documents (synced to iCloud)
mv ~/Documents/your-repo ~/dev/your-repoUpdate IDE/editor settings:
After moving, update any workspace files, IDE projects, or scripts that reference the old path.
Clone fresh if the repository is corrupted:
# If the repo is too damaged, clone a fresh copy
cd ~/dev
git clone https://github.com/user/repo.git
# Or from a local backup/remote
git clone /path/to/backup/repo.gitSafe locations for Git repositories:
- ~/dev - Development folder (not synced)
- ~/code - Code directory (not synced)
- /usr/local/src - System source directory
- Any folder NOT in Desktop, Documents, or iCloud Drive
If you want to keep repositories in Documents but prevent iCloud sync issues:
Disable Desktop & Documents sync:
macOS Ventura+:
1. Open System Settings > Apple ID > iCloud > iCloud Drive
2. Click Options or the info button
3. Turn OFF Desktop & Documents Folders
macOS Monterey and earlier:
1. Open System Preferences > Apple ID > iCloud
2. Click Options next to iCloud Drive
3. Uncheck Desktop & Documents Folders
What happens:
- Files in Desktop and Documents will no longer sync to iCloud
- Existing files remain but stop syncing
- You'll need alternative backup for these folders
After disabling:
# Verify Documents is no longer synced
ls -la ~/Documents
# Files should no longer have cloud status
xattr -l ~/Documents/your-repoAlternative: Use .nosync extension
Files or folders with .nosync in the name are excluded from iCloud sync:
# Rename folder to prevent sync
mv ~/Documents/my-repo ~/Documents/my-repo.nosyncNote: This is a workaround and may not be fully reliable.
iCloud sync conflicts can create duplicate ref files that break Git:
Check for duplicate refs:
cd /path/to/your/repo
# Look for numbered suffixes (indicates sync conflicts)
ls -la .git/refs/heads/
ls -la .git/refs/remotes/origin/Symptoms of ref conflicts:
- Files like main 2 or master 2 in refs/heads
- Error: fatal: bad object refs/heads/main 2
- Error: fatal: Could not parse object <hash>
Fix duplicate refs:
# Backup .git first!
cp -r .git .git-backup
# Remove the conflicting duplicate
# Keep the original, remove the one with suffix
rm ".git/refs/heads/main 2"
# Or if only the suffixed version exists, rename it
mv ".git/refs/heads/main 2" .git/refs/heads/mainRebuild refs if corrupted:
# Fetch fresh refs from remote
git fetch origin
# Reset local branches to match remote
git checkout main
git reset --hard origin/mainVerify refs are clean:
# Check for any remaining conflicts
find .git/refs -name "* *" # Files with spaces
# Validate repository
git fsck --fullIf you must store repositories in iCloud, use a disk image container:
Create a sparse bundle:
# Create a sparse disk image (grows as needed, max 50GB)
hdiutil create -size 50g -type SPARSEBUNDLE -fs "APFS" -volname "GitRepos" ~/Library/Mobile\ Documents/com~apple~CloudDocs/GitRepos.sparsebundleMount the disk image:
# Mount it
hdiutil attach ~/Library/Mobile\ Documents/com~apple~CloudDocs/GitRepos.sparsebundle
# It will mount at /Volumes/GitRepos
cd /Volumes/GitReposMove repositories into the image:
# Clone or move repositories into the mounted volume
git clone https://github.com/user/repo.git /Volumes/GitRepos/repoBenefits:
- iCloud sees it as a single file container
- Internal files won't be individually evicted
- Git operations work normally inside the image
- The sparse bundle syncs as a unit
Automate mounting (optional):
Create a script or use Login Items to mount the sparse bundle at startup:
#!/bin/bash
hdiutil attach ~/Library/Mobile\ Documents/com~apple~CloudDocs/GitRepos.sparsebundle -nobrowseUnmount when done:
hdiutil detach /Volumes/GitReposIf the repository is too corrupted to repair, here are recovery options:
Option 1: Clone fresh and copy changes:
# Clone a fresh copy from remote
cd ~/dev
git clone https://github.com/user/repo.git repo-fresh
# Copy uncommitted changes from corrupted repo (if any)
# First, list what files have changes
cd /path/to/corrupted/repo
git status # May fail, use ls instead
# Manually copy changed files
cp -r src/* ~/dev/repo-fresh/src/Option 2: Recreate from working directory:
# If .git is corrupted but files are intact
cd /path/to/corrupted/repo
# Remove corrupted .git
rm -rf .git
# Initialize fresh repository
git init
# Add remote and fetch history
git remote add origin https://github.com/user/repo.git
git fetch origin
# Reset to remote state, keeping local changes
git reset origin/main
# Now you can commit your local changes
git status
git add .
git commit -m "Recovered local changes"Option 3: Use git-repair:
# Install git-repair (via Homebrew)
brew install git-repair
# Attempt automatic repair
cd /path/to/repo
git-repair --forceOption 4: Recover objects from other clones:
# If you have another clone of the repo
git remote add recovery /path/to/other/clone
git fetch recoveryFollow these best practices to avoid iCloud-Git conflicts:
Repository location:
# Store repos in dedicated non-synced directories
mkdir -p ~/dev ~/code ~/projectsUse proper Git hosting for sync:
Instead of iCloud, use Git remotes for repository synchronization:
# GitHub, GitLab, or Bitbucket for remote backup
git remote add origin [email protected]:user/repo.git
git push -u origin mainExclude .git from cloud sync (if repo must be in synced folder):
Some cloud clients allow folder exclusions. For iCloud, this is limited, but you can try:
# Add extended attribute to prevent sync (may not work reliably)
xattr -w com.apple.fileprovider.ignore 1 .gitRegular repository maintenance:
# Periodically verify repository integrity
git fsck --full
# Compact repository to reduce number of loose objects
git gc --aggressiveBefore working on a synced repository:
# Always ensure files are downloaded first
cd /path/to/repo
find .git -type f -exec brctl download {} \;
# Wait a moment for downloads
sleep 5
# Then proceed with Git operations
git statusBackup .git directory:
# Create local backup before major operations
cp -r .git .git-backup-$(date +%Y%m%d)After applying fixes, verify Git is working properly:
Basic verification:
cd /path/to/your/repo
# Check repository status
git status
# View recent history
git log --oneline -10
# Check for any corruption
git fsck --fullTest file operations:
# Create and commit a test file
echo "test" > test-file.txt
git add test-file.txt
git commit -m "Test commit after iCloud fix"
# Remove test file
git rm test-file.txt
git commit -m "Remove test file"Test branch operations:
# Create and switch branches
git checkout -b test-branch
git checkout main
git branch -d test-branchVerify no evicted files remain:
# Check for any remaining .icloud files
find . -name '*.icloud' -o -name '.*icloud'
# Should return empty if all files are downloadedMonitor for recurring issues:
# Check iCloud status periodically
brctl status
# List evicted files in iCloud Drive
find ~/Library/Mobile\ Documents -name '*.icloud' | head -20If issues persist, consider moving the repository to a non-synced location permanently.
### How iCloud Drive File Eviction Works
macOS's "Optimize Mac Storage" feature uses a file provider system to manage local storage. When enabled, iCloud can "evict" files - removing their local content while keeping a lightweight placeholder. The placeholder file has the original filename prefixed with a dot and suffixed with .icloud (e.g., .README.md.icloud).
When you access an evicted file through Finder or most macOS applications, the system automatically triggers a download from iCloud. However, Git doesn't use the standard macOS file access APIs that trigger this automatic download. Instead, Git attempts to read the placeholder file directly, which contains metadata rather than the actual file content.
### The brctl Command
brctl (Bird Control) is an undocumented Apple utility for managing iCloud Drive:
# Download a file from iCloud
brctl download /path/to/file
# Evict a file (remove local copy)
brctl evict /path/to/file
# Monitor iCloud activity
brctl log -w -t
# Check iCloud status
brctl statusThe command accepts paths without the .icloud extension - use the original filename.
### FileProvider in macOS Sonoma and Later
Starting with macOS Sonoma, Apple uses the FileProvider framework more extensively for iCloud Drive operations. The fileproviderctl command provides alternative functionality:
# Download (materialize) a file
fileproviderctl materialize /path/to/file
# Evict a file
fileproviderctl evict /path/to/fileThis works with third-party cloud providers (Google Drive, Dropbox) that use FileProvider, unlike brctl which is iCloud-specific.
### Why Git and iCloud Don't Mix Well
Several technical factors make Git repositories problematic in iCloud Drive:
1. File eviction: Git needs immediate access to all repository files, especially in .git/objects
2. Sync timing: iCloud sync is asynchronous and can leave repositories in inconsistent states
3. Conflict resolution: iCloud creates duplicate files with numbered suffixes during conflicts, breaking Git's ref naming
4. Symbolic links: iCloud Drive ignores symlinks, but Git tracks them, causing divergent states across machines
5. Hidden files: iCloud may handle dotfiles (.git, .gitignore) differently than regular files
6. Lock files: Git uses lock files that can cause sync conflicts
### Detecting iCloud Issues Programmatically
# Check if a file is evicted (has extended attributes)
xattr -l filename
# Look for com.apple.fileprovider.* attributes
xattr -p com.apple.fileprovider.content-policy filename 2>/dev/null
# Find all evicted files in a directory
find . -name '.*icloud'
# Check file's iCloud status via mdls
mdls -name kMDItemIsUbiquitous -name kMDItemInICloudDrive filename### Working with Multiple Macs
If you use the same Apple ID on multiple Macs:
1. Avoid simultaneous work on repositories in iCloud Drive
2. Wait for sync before switching machines (check brctl status)
3. Use Git remotes (GitHub, GitLab) for synchronization instead of iCloud
4. Close IDEs before switching machines to flush file changes
### The Sparse Bundle Solution
Using a sparse disk image provides a workaround because:
- iCloud treats the entire sparse bundle as a single container
- Individual files inside aren't subject to eviction
- The container syncs atomically (more or less)
- Git operations inside the mounted image work normally
However, this approach has limitations:
- Large repositories create large containers
- Sync conflicts at the container level are harder to resolve
- Must manually mount/unmount the image
- Not suitable for active development with frequent syncs
### Alternative Approaches
1. Use a NAS or local server for repository storage with Git SSH access
2. Use a self-hosted Git server (Gitea, GitLab CE) on local network
3. Use Git LFS for large files and keep them out of iCloud
4. Use Git worktrees with the main .git directory outside iCloud
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