GitLab rejects pushes when files exceed the configured maximum file size limit. This can be a push rule set at the project, group, or instance level, or the 100 MiB limit enforced on GitLab.com Free tier. Remove the large file from your commit history using BFG or git filter-repo, then use Git LFS for ongoing large file management.
This error occurs when you attempt to push commits containing files that exceed GitLab's maximum allowed file size limit. GitLab enforces file size limits through its push rules feature, which can be configured at different levels: **1. GitLab.com Free Tier:** A strict 100 MiB per-file limit applies to all projects in the Free tier. This limit cannot be changed and applies automatically. **2. Push Rules (Premium/Ultimate):** Administrators can set custom file size limits at the project, group, or instance level. When you see this error on a self-managed GitLab instance or paid tier, a push rule with a maximum file size setting is likely configured. **3. Repository Size Limits:** Separate from file size limits, GitLab can also enforce overall repository size limits that might cause similar rejection messages. The key thing to understand is that even if you delete the large file from your working directory and commit that deletion, Git still stores the file in your commit history. You need to rewrite history to completely remove the file and successfully push. Push rules work as templates in GitLab - they are copied to projects at creation time but don't automatically inherit updates. This means different projects in your organization might have different file size limits.
First, identify which files exceed the limit. GitLab's error message often shows file IDs instead of names.
If you see a file ID in the error:
# Match the file ID to an actual filename
tree -r | grep <file-id>
# Or search for the file by ID in git objects
git rev-list --objects --all | grep <file-id>Find all large files in your repository:
# List files larger than 100MB in current working tree
find . -type f -size +100M -not -path "./.git/*"
# Find large files in git history
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ {print substr($0,6)}' | \
sort -rnk2 | \
head -20Check which commits contain the large file:
# Find commits that modified a specific file
git log --all --full-history -- "path/to/large_file"
# See file sizes in current HEAD
git ls-tree -r -l HEAD | sort -k4 -rn | head -20Determine what file size limit is configured for your GitLab project:
For GitLab.com Free tier:
The limit is fixed at 100 MiB per file and cannot be changed. You'll need to upgrade to a paid tier or use Git LFS.
For projects with push rules (Premium/Ultimate):
1. Go to your project in GitLab
2. Navigate to Settings > Repository
3. Expand Push rules
4. Check the Maximum file size (MB) setting
For group-level rules:
1. Go to your group
2. Navigate to Settings > Repository
3. Expand Push rules
4. Check the configured maximum file size
For instance-level settings (self-managed):
1. Go to Admin Area > Push Rules to see default rules for new projects
2. Go to Admin Area > Settings > General > Account and limit for maximum push size
Note: Setting the limit to 0 disables the file size check. If you're an admin, you can temporarily increase or disable the limit to allow a push, then re-enable it.
BFG Repo-Cleaner is the fastest way to remove large files from your git history.
Install BFG:
# macOS
brew install bfg
# Or download the JAR from https://rtyley.github.io/bfg-repo-cleaner/
# Requires Java 11+Create a mirror clone:
git clone --mirror https://gitlab.com/username/repo.git repo.git
cd repo.gitRemove large files:
# Remove all files larger than 100MB
bfg --strip-blobs-bigger-than 100M
# Or remove specific files
bfg --delete-files large_file.zip
# Or remove by pattern
bfg --delete-files "*.zip"Clean up and push:
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push --forceNote: BFG protects your current HEAD commit. If the large file is in your latest commit, delete it and commit first, then run BFG.
git filter-repo is the officially recommended tool for history rewriting, replacing the deprecated git filter-branch.
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.zip"
# Remove multiple files
git filter-repo --invert-paths --path "file1.zip" --path "data.tar.gz"
# Remove by pattern
git filter-repo --invert-paths --path-glob "*.zip"
# Remove all files larger than a size
git filter-repo --strip-blobs-bigger-than 100MRe-add remote and push:
# filter-repo removes the remote for safety
git remote add origin https://gitlab.com/username/repo.git
# Force push all branches and tags
git push origin --force --all
git push origin --force --tagsIf the large file was added in the last few unpushed commits, interactive rebase is simpler:
For the last commit:
# Undo the last commit, keeping changes staged
git reset --soft HEAD~1
# Remove the large file from staging
git rm --cached path/to/large_file
# Add to .gitignore to prevent future accidents
echo "path/to/large_file" >> .gitignore
git add .gitignore
# Re-commit without the large file
git commit -m "Your original commit message"For a commit a few commits back:
# Start interactive rebase (N = number of commits to go back)
git rebase -i HEAD~N
# In the editor, change 'pick' to 'edit' for the problematic commit
# Save and close
# Remove the large file
git rm --cached path/to/large_file
git commit --amend --no-edit
# Continue the rebase
git rebase --continueWarning: Don't use this method if you've already pushed these commits to a shared branch.
Git LFS (Large File Storage) is GitLab's recommended solution for handling large files. Files tracked by LFS are exempt from push rule size limits.
Install Git LFS:
# macOS
brew install git-lfs
# Ubuntu/Debian
apt install git-lfs
# Windows (usually included with Git for Windows)
git lfs install
# Initialize for your user (once per machine)
git lfs installTrack large file types:
# Track specific file extensions
git lfs track "*.zip"
git lfs track "*.tar.gz"
git lfs track "*.psd"
git lfs track "*.mp4"
# Track a specific file
git lfs track "data/large_dataset.csv"
# This updates .gitattributes
git add .gitattributes
git commit -m "Configure Git LFS tracking"Migrate existing files to LFS:
# Import existing large files (rewrites history)
git lfs migrate import --include="*.zip" --everything
# Force push the rewritten history
git push origin --force --allGitLab LFS storage:
- GitLab.com Free: 5 GB storage included
- Paid tiers: Additional storage available
- Self-managed: Depends on instance configuration
If you're on a paid GitLab tier or self-managed instance, you may be able to request a limit increase.
For project maintainers (Premium/Ultimate):
1. Go to Settings > Repository > Push rules
2. Increase or remove the Maximum file size (MB) setting
3. Select Save push rules
For group owners:
1. Go to your group's Settings > Repository > Push rules
2. Adjust the maximum file size
3. Note: This only affects new projects, not existing ones
For GitLab administrators (self-managed):
# Via Rails console
gitlab-rails console
# Remove instance-wide file size limit
PushRule.find_by(is_sample: true).update!(max_file_size: 0)Or via the Admin Area:
1. Go to Admin Area > Push Rules
2. Set Maximum file size (MB) to 0 (unlimited) or your desired limit
3. Save changes
Note: Changing instance or group rules doesn't update existing projects automatically - each project maintains its own copy of the push rules.
After removing the large file from history, push your changes to GitLab:
Verify the large file is removed:
# Check for files larger than the limit
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ && $3 > 104857600 {print}' # 100MB in bytes
# Should return empty if successfulForce push to GitLab:
# Push main branch
git push origin main --force
# Or use --force-with-lease for safety
git push origin main --force-with-lease
# Push all branches
git push origin --force --all
# Push tags
git push origin --force --tagsAfter force pushing, notify your team:
# Team members should run:
git fetch origin
git reset --hard origin/main
# Or re-clone the repository
rm -rf repo && git clone https://gitlab.com/username/repo.gitFor protected branches:
If the branch is protected, you may need to temporarily allow force pushes:
1. Go to Settings > Repository > Protected branches
2. Edit the branch protection
3. Enable Allowed to force push
4. Push your changes
5. Disable force push again
Set up safeguards to prevent accidentally committing large files again:
Update .gitignore:
# Add patterns for common large files
cat >> .gitignore << 'EOF'
# Large files
*.zip
*.tar.gz
*.rar
*.7z
*.iso
# Media files
*.mp4
*.mov
*.avi
*.psd
*.ai
# Data files
*.csv
*.sql
*.sqlite
*.parquet
data/
# Build artifacts
dist/
build/
*.exe
*.dll
# Dependencies
node_modules/
vendor/
EOF
git add .gitignore
git commit -m "Update .gitignore to exclude large files"Set up 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); do
if [ -f "$file" ]; then
size=$(wc -c < "$file")
if [ $size -gt $MAX_SIZE ]; then
echo "Error: $file is larger than 50MB ($size bytes)"
echo "Use Git LFS for large files: git lfs track "$file""
exit 1
fi
fi
done
EOF
chmod +x .git/hooks/pre-commitUse pre-commit framework:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-added-large-files
args: ['--maxkb=51200'] # 50MB### Understanding GitLab Push Rules
Push rules in GitLab work as templates, not inherited settings. When you create global push rules (Admin Area > Push Rules), they are copied to all new projects created after that point. However:
- Existing projects are not affected by changes to global rules
- Project rules are independent copies that don't auto-update
- If you delete project push rules, the project does NOT revert to global rules
- Push rules are bypassed during fork synchronization
This means different projects in your organization might have different file size limits depending on when they were created and whether rules were manually modified.
### GitLab.com Tier Differences
| Tier | Per-File Limit | Configurable | LFS Storage |
|------|----------------|--------------|-------------|
| Free | 100 MiB | No | 5 GB |
| Premium | Configurable via push rules | Yes | 10 GB |
| Ultimate | Configurable via push rules | Yes | 10 GB |
### Repository Size vs File Size Limits
GitLab has two separate size limits:
1. Maximum file size (push rules): Limits individual file sizes
2. Repository size limit: Limits total repository size including LFS objects
The repository size limit includes:
- Repository files (all branches/tags)
- Git LFS objects
It excludes:
- Artifacts
- Container registry
- Packages
- Snippets
- Uploads
- Wikis
### GitLab LFS Configuration
For self-managed GitLab, ensure LFS is enabled:
# /etc/gitlab/gitlab.rb
gitlab_rails['lfs_enabled'] = true
gitlab_rails['lfs_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/lfs-objects"
# For object storage (recommended for large deployments)
gitlab_rails['lfs_object_store_enabled'] = true
gitlab_rails['lfs_object_store_remote_directory'] = "gitlab-lfs"
gitlab_rails['lfs_object_store_connection'] = {
'provider' => 'AWS',
'region' => 'us-east-1',
'aws_access_key_id' => 'ACCESS_KEY',
'aws_secret_access_key' => 'SECRET_KEY'
}### CI/CD Considerations
If your CI/CD pipelines involve pushing to repositories, ensure runners have appropriate permissions and that the GitLab token used has push access:
# .gitlab-ci.yml
push_changes:
script:
- git config user.email "[email protected]"
- git config user.name "CI Bot"
- git remote set-url origin "https://oauth2:${CI_JOB_TOKEN}@gitlab.com/group/project.git"
- git push origin HEAD:main
rules:
- if: $CI_COMMIT_BRANCH == "main"Note that CI_JOB_TOKEN has limited permissions. For pushing changes, you may need a Project Access Token with write_repository scope.
### Comparing BFG vs git filter-repo
| Feature | BFG | git filter-repo |
|---------|-----|-----------------|
| Speed | Very fast | Fast |
| Installation | Requires Java | Python-based |
| Ease of use | Very simple | More options |
| HEAD protection | Built-in | Manual |
| Pattern matching | Basic | Advanced regex |
Recommendation: Use BFG for simple file removal, git filter-repo for complex rewrites.
### Recovering If Push Partially Succeeded
If some commits pushed before the rejection:
# Check what made it to remote
git fetch origin
git log origin/main..HEAD
# You may need to coordinate with team
# before rewriting shared history### Debugging Push Rule Rejections
To see exactly why a push was rejected:
# Increase Git verbosity
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push origin main
# Check GitLab's response in the outputFor self-managed GitLab, check the logs:
# Gitaly logs
sudo gitlab-ctl tail gitaly
# Rails logs
sudo gitlab-ctl tail rails-webkex_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