GitHub rejects pushes when files exceed 100 MB, displaying the GH001 error code. To fix this, you must remove the large file from your commit history using git reset, BFG Repo-Cleaner, or git filter-repo, then either exclude the file from version control or set up Git LFS to handle large files.
This error occurs when you attempt to push commits to GitHub that contain one or more files larger than 100 MB. GitHub enforces a strict per-file size limit, and the GH001 error code specifically indicates that large files were detected during the push operation. The critical detail many developers miss is that simply deleting the large file from your working directory doesn't solve the problem. Git stores every version of every file in its history, so even if you delete the file and commit the deletion, the original version still exists in your repository's commit history. When you push, GitHub scans all commits being pushed - including historical ones - and rejects the entire push if any commit contains an oversized file. GitHub displays this error proactively to protect repository performance. Large binary files don't diff well in Git (each version is stored in full), and they can dramatically slow down clones, fetches, and other operations. For files that legitimately need version control but exceed the limit, GitHub provides Git Large File Storage (LFS) as a solution. Note: GitHub warns you about files over 50 MB but allows them through. The hard rejection happens at 100 MB. This error also appears if you're pushing a branch that includes commits from another contributor who added the large file.
The error message shows which files exceeded the limit, but you can also scan your repository:
# Find files larger than 100MB in your repository history
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ {print substr($0,6)}' | \
sort -rnk2 | \
head -20Find which commits contain the problematic file:
# Show commits that modified the large file
git log --all --full-history -- "path/to/large_file.bin"
# Check the current size
git ls-tree -r -l HEAD | sort -k 3 -n -r | head -10Note the exact file path - you'll need it for the removal steps. The path shown in the error message is relative to your repository root.
If you just added the large file and haven't pushed any other commits since, this is the simplest fix:
# Undo the last commit but keep all changes in your working directory
git reset --soft HEAD~1
# Remove the large file from staging
git reset HEAD path/to/large_file.bin
# Add the file to .gitignore so it won't be committed again
echo "path/to/large_file.bin" >> .gitignore
# Or use a pattern: echo "*.bin" >> .gitignore
# Stage and commit everything except the large file
git add .
git commit -m "Your commit message (without large file)"If the large file was added multiple commits ago, check how many commits you're ahead:
git status
# Shows: Your branch is ahead of 'origin/main' by N commits
# Reset back N commits (keeps your changes)
git reset HEAD~N
# Now selectively re-add and commit without the large fileIf the large file is buried in your commit history, BFG Repo-Cleaner is the fastest and easiest solution:
Install BFG:
# macOS
brew install bfg
# Or download the JAR from https://rtyley.github.io/bfg-repo-cleaner/
# Requires Java 11+Remove the large file:
# First, delete the file from your current commit if present
git rm path/to/large_file.bin
git commit -m "Remove large file"
git push # This will still fail, that's okay
# Clone a fresh mirror of your repo
git clone --mirror https://github.com/username/repo.git repo.git
cd repo.git
# Remove all files larger than 100MB from history
bfg --strip-blobs-bigger-than 100M
# Or remove a specific file by name
bfg --delete-files large_file.bin
# Clean up the repository
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# Push the cleaned history
git push --forceImportant: BFG won't modify your latest commit (HEAD) by default. Delete the file from HEAD first before running BFG.
git filter-repo is the modern replacement for git filter-branch, recommended by the Git project itself:
Install git filter-repo:
# macOS
brew install git-filter-repo
# pip (any platform)
pip install git-filter-repo
# Ubuntu/Debian
apt install git-filter-repoRemove the large file:
# Remove a specific file from all history
git filter-repo --invert-paths --path "path/to/large_file.bin" --force
# Remove files by extension
git filter-repo --invert-paths --path-glob "*.bin" --force
# Remove all files larger than 100MB
git filter-repo --strip-blobs-bigger-than 100M --forceRe-add remote and push:
# filter-repo removes the remote for safety; re-add it
git remote add origin https://github.com/username/repo.git
# Force push all branches and tags
git push origin --force --all
git push origin --force --tagsIf you genuinely need to version control large files (design assets, datasets, etc.), use Git Large File Storage:
Install Git LFS:
# macOS
brew install git-lfs
# Windows (included with Git for Windows)
git lfs install
# Ubuntu/Debian
apt install git-lfs
# Initialize LFS (once per machine)
git lfs installTrack large file patterns:
# Track by extension
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.zip"
# Track a specific file
git lfs track "assets/large_dataset.bin"
# Commit the .gitattributes file
git add .gitattributes
git commit -m "Configure Git LFS tracking"Migrate existing files to LFS:
# Convert existing files in history to LFS
git lfs migrate import --include="*.bin" --everything
# Force push the rewritten history
git push origin --force --allNote: GitHub provides 1 GB free LFS storage and 1 GB bandwidth per month. Additional data packs cost $5/month for 50 GB.
Set up safeguards to catch large files before they're committed:
Update .gitignore:
# Add common large file patterns
cat >> .gitignore << 'EOF'
# Large binaries
*.zip
*.tar.gz
*.rar
*.7z
*.bin
# Media files
*.mp4
*.mov
*.psd
*.ai
# Build artifacts
dist/
build/
*.exe
*.dll
# Dependencies
node_modules/
vendor/
# Data files
*.csv
*.sql
*.sqlite
EOF
git add .gitignore
git commit -m "Add patterns to prevent large file commits"Create a pre-commit hook:
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
# Block commits with files larger than 50MB
MAX_SIZE=$((50 * 1024 * 1024))
for file in $(git diff --cached --name-only --diff-filter=ACM); do
if [ -f "$file" ]; then
size=$(wc -c < "$file" | tr -d ' ')
if [ "$size" -gt "$MAX_SIZE" ]; then
echo "ERROR: $file is $(($size / 1024 / 1024))MB (limit: 50MB)"
echo "Use Git LFS for large files: git lfs track '$file'"
exit 1
fi
fi
done
EOF
chmod +x .git/hooks/pre-commitAfter rewriting history, you must force push and inform your team:
Verify the file is removed:
# Check for any remaining large files
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ && $3 > 100000000 {print}'
# Should return nothing if all large files are removedForce push safely:
# Use --force-with-lease for safety (fails if remote changed)
git push origin main --force-with-lease
# Or force push all branches
git push origin --force --all
git push origin --force --tagsTeam members must resync:
# Option 1: Re-clone (cleanest)
cd ..
rm -rf repo
git clone https://github.com/username/repo.git
# Option 2: Hard reset
git fetch origin
git reset --hard origin/mainWarning: Coordinate with your team before force pushing. Anyone with unpushed commits will need to rebase their work onto the new history.
### Why Deleting the File Doesn't Fix the Error
Git stores a complete snapshot of every file at every commit. When you delete a file and commit, you're just creating a new commit that doesn't reference that file - but all previous commits still contain the file's data.
GitHub scans every commit you're pushing (not just the tip), so if any commit in your branch history contains a 100 MB+ file, the push is rejected. This is why you need history-rewriting tools.
### The GH001 Error Code
GH001 is GitHub's specific error code for large file detection. Related GitHub error codes include:
- GH002: Multiple accounts detected
- GH003: Anonymous pushes to public repos
- GH006: Protected branch policy violation
### Platform Comparison
| Platform | Per-File Limit | Push Limit | LFS Storage |
|----------|---------------|------------|-------------|
| GitHub | 100 MB | 2 GB | 1 GB free |
| GitLab | 100 MB* | Unlimited | 10 GB free |
| Bitbucket | 100 MB | 2 GB | 1 GB free |
*GitLab allows administrators to configure custom limits on self-hosted instances.
### BFG vs git filter-repo
BFG Repo-Cleaner:
- Fastest option (10-720x faster than filter-branch)
- Simple command-line interface
- Requires Java runtime
- Best for: removing large files, passwords, credentials
git filter-repo:
- Recommended by Git maintainers
- More flexible path and content filtering
- Python-based
- Best for: complex history rewrites
Both tools produce the same result - rewritten commits without the large file.
### Git LFS Internals
Git LFS works by replacing large files with small "pointer" files in your Git repository. The actual file content is stored on a separate LFS server. When you clone or checkout, Git LFS downloads the real files automatically.
Pointer files look like:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345678### Handling Protected Branches
If you can't force push due to branch protection:
1. Go to Settings > Branches in your GitHub repository
2. Edit the protection rules for the affected branch
3. Temporarily allow force pushes (or disable protection)
4. Push your cleaned history
5. Re-enable branch protection immediately
Alternatively, create a new branch from your cleaned history and delete the old branch.
### CI/CD Considerations
If your CI/CD pipeline clones the repository, it may cache the old refs. After rewriting history:
1. Clear CI caches manually
2. Use git clone --depth 1 for shallow clones in CI
3. Update any hardcoded commit SHAs in your pipeline configuration
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