The 'unable to read alternates file' error occurs when Git cannot access an alternate object database that was previously linked. This typically happens when a reference repository was deleted, moved, or when paths become invalid after moving the repository.
This error indicates that Git cannot read the alternates file located at `.git/objects/info/alternates`. The alternates mechanism is a space-saving feature that allows one Git repository to reference objects (commits, trees, blobs) from another repository instead of storing duplicate copies. When you clone a repository using `git clone --reference` or `git clone --shared`, Git creates an alternates file that points to another repository's object store. This is commonly used in CI/CD environments or when working with multiple forks of the same large repository to avoid downloading the same objects multiple times. The error occurs when Git tries to read objects but the path specified in the alternates file is either: 1. **No longer valid** - The reference repository was deleted or moved 2. **Inaccessible** - Permission changes prevent reading the alternate repository 3. **Malformed** - The alternates file contains invalid path syntax 4. **Unreachable** - In containerized environments, the mounted path doesn't exist This is a serious error because Git cannot access objects it believes should exist, which can break nearly all Git operations including `git add`, `git commit`, `git pull`, and `git log`.
First, examine what alternate object stores your repository is configured to use:
# View the alternates file
cat .git/objects/info/alternatesThis file contains paths to other Git object directories, one per line. Common examples:
/home/shared/repo.git/objects
../reference-repo/.git/objectsVerify each path exists:
# Check if the path exists
ls -la /path/from/alternates/fileIf any path doesn't exist or is inaccessible, that's your problem.
If you no longer need object sharing or the reference repository is gone, simply remove the alternates file:
# Remove the alternates file
rm .git/objects/info/alternatesImportant: After removing the alternates file, your repository may be missing objects. Run a verification:
# Check for missing objects
git fsck --fullIf objects are missing, you'll need to either:
1. Fetch them from the remote
2. Restore from a backup
3. Repack the repository (see next step)
If your repository was dependent on the alternate object store, you can fetch missing objects from the remote and repack:
# First, try to fetch all objects from remote
git fetch --all
# Repack all objects into the local repository
git repack -a -d
# Remove the alternates file after repacking
rm -f .git/objects/info/alternates
# Verify the repository is complete
git fsck --fullThe git repack -a -d command:
- -a - Repack all objects into new pack files
- -d - Remove redundant loose objects
This creates a self-contained repository that no longer depends on alternates.
If starting fresh is an option, clone with the --dissociate flag to get the benefits of --reference without the long-term dependency:
# Clone using reference but immediately dissociate
git clone --reference /path/to/reference/repo --dissociate <remote-url>The --dissociate flag tells Git to:
1. Use the reference repository during initial clone (faster)
2. Immediately copy any borrowed objects into the new clone
3. Remove the alternates reference after cloning
This gives you the speed benefit of a reference clone without creating a dependency on the reference repository existing forever.
For existing repository:
# If you want to dissociate an existing clone
git repack -a -d
rm .git/objects/info/alternatesIf the reference repository still exists but at a different location, update the alternates file:
# Edit the alternates file
nano .git/objects/info/alternates
# Or replace the path directly
echo "/new/path/to/reference/.git/objects" > .git/objects/info/alternatesPath format guidelines:
- Use absolute paths when possible
- On Windows, use forward slashes: C:/Users/name/repo/.git/objects
- Each path should point to a .git/objects directory
- One path per line, no trailing whitespace
Verify the new path works:
# Test if Git can read objects
git fsck --fullIf the reference repository exists but Git cannot read it, check permissions:
# Check permissions on the reference repository
ls -la /path/to/reference/.git/objects
# The objects directory and its contents need read access
# For a shared reference repository, set group read permissions:
chmod -R g+rX /path/to/reference/.git/objectsCommon permission scenarios:
- User running Git changed (different account)
- CI/CD runner user differs from setup user
- Docker container running as different UID
For shared team reference repositories:
# Make the reference repository readable by all
chmod -R a+rX /path/to/reference/.gitIn Docker or containerized environments, alternates often break because paths inside the container differ from paths on the host:
Problem scenario:
# Host created a reference clone at /home/user/reference
# Container sees the world differently
docker run -v /home/user/reference:/mnt/reference ...
# But alternates file still points to /home/user/referenceSolutions:
Option 1: Mount reference at the same path
docker run -v /home/user/reference:/home/user/reference ...Option 2: Dissociate before containerizing
# On host, before building container
git repack -a -d
rm .git/objects/info/alternatesOption 3: Update alternates for container paths
# Inside container
echo "/mnt/reference/.git/objects" > .git/objects/info/alternatesFor CI/CD pipelines: Always use --dissociate when cloning with --reference to avoid this class of problems entirely.
### Understanding Git Alternates
The alternates mechanism is part of Git's object storage system. Instead of duplicating objects, Git can reference objects from another repository. This is controlled by the file at .git/objects/info/alternates.
How it works:
1. When Git needs an object (commit, tree, blob), it first looks in .git/objects
2. If not found, Git reads paths from .git/objects/info/alternates
3. Git searches each alternate object store in order
4. If still not found, Git reports the object as missing
### Clone Options That Create Alternates
`git clone --reference <repo>`
# Uses local repo as reference, creates alternates entry
git clone --reference /path/to/local/repo https://github.com/org/repo.git- Fetches objects not in reference from remote
- Creates permanent dependency on reference repository
- Reference repository must remain accessible
`git clone --shared`
# Clone from local repository with shared objects
git clone --shared /path/to/local/repo ./new-clone- Only works with local repositories
- Creates alternates pointing to source
- Both repositories share the same objects
`git clone --dissociate`
# Use reference but immediately copy objects
git clone --reference /path/to/ref --dissociate https://github.com/org/repo.git- Copies borrowed objects into the new clone
- Removes alternates after cloning
- No long-term dependency
### CI/CD Best Practices
For build systems and CI pipelines, reference clones can significantly speed up operations but require careful management:
# Safe pattern for CI/CD
if [ -d "/cache/reference/.git" ]; then
git clone --reference /cache/reference --dissociate "$REPO_URL" .
else
git clone "$REPO_URL" .
fiKey considerations:
- Always use --dissociate in ephemeral environments
- Cache the reference repository, not the clone
- Periodically refresh the reference cache
- Handle missing reference gracefully
### Recovering from Severe Corruption
If your repository is severely broken and you have a remote:
# Back up your work directory (not .git)
cp -r . ../backup-workdir
# Get a fresh clone
cd ..
rm -rf broken-repo
git clone <remote-url> fresh-repo
# Copy your uncommitted changes back
cp -r backup-workdir/* fresh-repo/### Object Sharing in Monorepos
Large organizations sometimes use alternates for monorepo setups:
# Central shared object store
/shared/git-objects/company-monorepo/.git/objects
# Each developer's clone references the shared store
echo "/shared/git-objects/company-monorepo/.git/objects" > .git/objects/info/alternatesRisks of this approach:
- Single point of failure
- Permission management complexity
- Network dependency for local operations
- Difficult to maintain across OS versions
Safer alternative: Use Git's partial clone or sparse checkout features instead of alternates for large repositories.
### Windows-Specific Path Issues
Windows paths in alternates files can be tricky:
# These formats work:
C:/Users/name/repo/.git/objects
/c/Users/name/repo/.git/objects
# This does NOT work:
C:\Users\name\repo\.git\objectsAlways use forward slashes, even on Windows, in the alternates file.
fatal: bad object in rev-list input
Git rev-list encounters bad or invalid object
fatal: Out of memory, malloc failed during pack operation
Out of memory during Git pack operation
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