Why is Your Git Repo So Bloated?
Have you ever found yourself waiting 15 minutes to git clone a small project, or having enough time to brew a cup of coffee every time you git fetch? I once handled a repo where the .git folder ballooned to 8GB, even though the actual source code was only a mere 120MB.
The truth is, the fault rarely lies with the code you write. The culprits are usually things we accidentally toss into the history: a 1GB dump.sql file, a mistakenly committed node_modules folder, or thousands of old tags that are never used. Git has an excellent memory—it will keep those mistakes forever unless you take action.
Instead of manually digging through every folder, I often use git-sizer. This is a “heavyweight weapon” for diagnosing and pinpointing exactly which components are weighing down your repository.
What is git-sizer and Why is it Different?
Usually, developers use the du -sh .git command to check the size. However, this general number doesn’t tell you why the repo is heavy.
The real value of git-sizer lies in its ability to dissect Git’s internal structure, such as objects, trees, blobs, and commits. It calculates key metrics including:
- Total number of commits and the maximum size of a single commit.
- A list of the largest blobs (files).
- Directory tree depth.
- The number of existing references (like branches and tags).
This tool rates your repo on a scale of 0 to 30+ stars. The more stars, the higher the risk that your repo will be rejected by servers like GitHub or cause your colleagues’ machines to run at a snail’s pace.
Installing git-sizer
Installation is very fast because it’s a single executable written in Go. For macOS users with Homebrew, just run:
brew install git-sizer
If you’re on Windows or Linux, download the pre-built binary from the GitHub Releases page and add it to your PATH. Alternatively, if you have Go installed, you can install it directly via:
go install github.com/github/git-sizer@latest
Hands-on: Analyzing a “Problematic” Repo
To start, navigate to the bloated repository directory and run:
git-sizer --verbose
The --verbose flag will list specific files in detail. Here are the actual results from a legacy project I once optimized:
| Name | Value | Level of concern |
| ---------------------------- | --------- | ------------------------------ |
| Overall repository size | | |
| * Total size of blobs | 1.52 GiB | * |
| * Total size of trees | 85.2 MiB | |
| * Total size of commits | 12.4 MiB | |
| | | |
| Biggest objects | | |
| * Maximum blob size | 450 MiB | ******************** (20 stars)|
| * Maximum tree size | 1.2 MiB | ** |
| | | |
| History structure | | |
| * Maximum commit depth | 15,402 | **** |
The Maximum blob size line receiving 20 stars is a red flag. It indicates that at least one file weighing 450MB is hidden in the history. Even if you deleted that file in the current commit, Git keeps it in .git to ensure you can checkout past versions.
Tracking Down the Culprit
Once I know there’s a large file, I usually use the following command to find its exact name:
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print $1}')"
This command matches IDs from git-sizer with actual filenames. In one real-world project, I discovered a developer had accidentally committed a 600MB video_demo.mp4 file. Knowing the exact filename makes the cleanup process extremely fast.
How to Optimize After Analysis
You can’t just use rm file then git commit to solve this. You need to perform surgery on the entire Git history.
1. Use git-filter-repo (The Best Choice)
This is a modern, safe, and much faster tool compared to the outdated git filter-branch. To permanently delete a heavy file from the history, use:
git filter-repo --path path/to/large/file --invert-paths
Important Note: This operation changes the hashes of old commits. You must inform the whole team to re-clone the repository after the cleanup.
2. Cleaning Up Redundant References
If git-sizer reports an issue in the Total number of references section, your repo has too many junk branches and tags. Delete branches that have been merged into main with this command:
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
Tips for Keeping Your Repo “Clean”
Cleaning up a multi-gigabyte repo is a nightmare. To avoid repeating these mistakes, I always apply three golden rules for my team:
- Set up a proper .gitignore: Thoroughly block logs, build artifacts, and dependency folders like
node_modulesfrom day one. - Use Git LFS: If the project must contain large files like AI models or 4K images, use Git LFS instead of committing them directly.
- Periodic Checks: Every 3 months, run git-sizer on the main branch to detect “stray” files early.
After implementing this process, my team’s CI/CD speed improved significantly. The time to fetch code to the build server dropped from 5 minutes to less than 30 seconds.
Conclusion
Git-sizer doesn’t fix errors directly, but it acts as a microscope that helps you see through all underlying issues. Don’t wait until your repo is so heavy it’s impossible to clone before you start worrying. Try running git-sizer today—the results might surprise you!

