Git LFS (Large File Storage) is a great tool for managing large files in Git repositories, but it can lead to unexpected storage costs on platforms like GitHub. If you’ve accidentally committed large files to LFS or no longer need them, here’s a comprehensive guide to find and remove them from both your local repository and GitHub.
The Problem
Git LFS storage is billable on GitHub. Even files that seem small can add up quickly, especially compressed log files, database dumps, or media files that were accidentally committed. In our case, we discovered 212MB of compressed web server log files (.gz) that were unnecessarily stored in LFS, costing money every month.
Step 1: Assess Your Current LFS Usage
First, let’s see what’s currently stored in LFS and how much space it’s using.
Check if LFS is configured
git lfs env
List files tracked by LFS
git lfs ls-files
Check local LFS storage size
# macOS/Linux
du -h .git/lfs/objects
# Alternative that works on all systems
find .git/lfs/objects -type f -exec ls -lh {} \;
Analyze what file types are using the most space
git lfs migrate info --everything
This command shows you which file patterns are consuming the most storage.
Step 2: Identify Unwanted LFS Files
Search for specific file types in git history
# Look for compressed files
git rev-list --objects --all | grep -E "\\.gz$"
# Look for other large file types
git rev-list --objects --all | grep -E "\\.(zip|tar|rar|7z|mp4|mov|avi|mkv|pdf|psd|ai)$"
Find commits that added these files
git log --name-only --grep="log" --oneline
git log --stat --all | grep -A5 -B5 "\.gz\|\.zip\|\.tar"
Step 3: Remove LFS Files from Local Repository
Option A: Remove LFS objects locally (temporary)
# Uninstall LFS (removes hooks and config)
git lfs uninstall
# Remove local LFS objects
rm -rf .git/lfs/objects
# Clean up remaining LFS references
git lfs prune
Note: This only removes files locally. They’ll still exist in the remote repository.
Step 4: Remove LFS Files from Git History (Permanent Solution)
To completely eliminate LFS storage costs, you need to remove the files from git history entirely.
Install git-filter-repo
# macOS with Homebrew
brew install git-filter-repo
# Linux with pip
pip3 install git-filter-repo
# Or install manually from: https://github.com/newren/git-filter-repo
Remove files from entire git history
# Remove a specific directory (like logs/)
git filter-repo --path logs/ --invert-paths --force
# Remove files by extension
git filter-repo --glob-filter="*.gz" --invert-paths --force
# Remove files by size (everything over 100MB)
git filter-repo --strip-blobs-bigger-than 100M --force
Important: This rewrites git history and changes commit hashes!
Step 5: Update Remote Repository
After cleaning your local repository, you need to force push to update the remote.
Re-add the remote (git-filter-repo removes it for safety)
git remote add origin [email protected]:username/repository.git
Force push the cleaned history
# Use force push to overwrite remote history
git push --force origin main
Warning: This will overwrite the remote repository’s history. Make sure your team is aware!
Step 6: Prevent Future Issues
Add problematic files to .gitignore
# Add directories that should never be committed
echo "logs/" >> .gitignore
echo "*.gz" >> .gitignore
echo "*.zip" >> .gitignore
echo "database_dumps/" >> .gitignore
# Commit the updated .gitignore
git add .gitignore
git commit -m "Add files to gitignore to prevent future LFS storage costs"
git push
Disable LFS if no longer needed
# Completely remove LFS configuration
git lfs uninstall --local
rm -f .gitattributes
Step 7: Verify the Cleanup
Check local LFS storage
git lfs ls-files # Should return nothing
du -h .git/lfs/ # Should show minimal storage (just cache)
Verify files are removed from history
git rev-list --objects --all | grep -E "\\.gz$" | wc -l # Should return 0
Check GitHub repository size
- Go to
https://github.com/username/repository/settings - Look for Repository size section
- Check Git LFS usage (should be 0 MB or minimal)
Check account-level LFS billing
- Visit
https://github.com/settings/billing/usage - Filter by Group: Repository to see usage by repo.
Important Considerations
Team Coordination
When you rewrite git history:
- All team members need to re-clone the repository or reset their local copies
- Existing pull requests may need to be recreated
- Any scripts or CI/CD that reference specific commit hashes will break
Alternative: BFG Repo-Cleaner
If you prefer an alternative to git-filter-repo:
# Install BFG
brew install bfg # macOS
# or download from: https://rtyley.github.io/bfg-repo-cleaner/
# Remove files
bfg --delete-files "*.gz" your-repo.git
Backup First
Before running any history-rewriting commands:
# Create a backup branch
git branch backup-before-lfs-cleanup
# Or clone a backup copy
git clone your-repo.git your-repo-backup
Results
In our case, we successfully:
- Removed 212MB of LFS objects (compressed log files)
- Eliminated ongoing LFS storage costs
- Cleaned both local and remote repositories
- Prevented future accidental commits with updated
.gitignore
The repository went from 212MB of billable LFS storage to 0MB, while maintaining all the important project files and history.
Conclusion
Git LFS storage costs can be eliminated by identifying unwanted files and removing them from git history entirely. While the process requires rewriting history (which has implications for team workflows), it’s often the only way to permanently resolve LFS billing issues.
The key steps are:
- Assess what’s using LFS storage
- Remove files from git history using git-filter-repo
- Force push to update the remote repository
- Prevent future issues with proper
.gitignorerules
Remember to coordinate with your team when rewriting history, and always create backups before running destructive operations.
This guide helped eliminate 212MB of unnecessary LFS storage costs. The same approach can be applied to any unwanted large files in your Git repository.
Leave a Reply