Find somethingAlways fixable

Find what's making your repository huge

My .git folder is enormous — how do I find the biggest files in history?

Short answer

git count-objects -vH tells you the total size; combining git rev-list --objects with git cat-file --batch-check lists the largest blobs by name. Deleting the files now won't shrink anything — they have to be purged from history.

quick fix
git count-objects -vH

Shows how much space the object database is actually using

Does this match your situation?

  • Cloning takes many minutes for a small codebase.
  • .git is far larger than your working directory.
  • A push is rejected for exceeding a file size limit.
  • CI checkouts are slow and getting slower.

Step-by-step fix

  1. Measure the damage

    size-pack is the number that matters — the compressed size of all history. Compare it to your working directory to see how disproportionate things are.

    step 1
    git count-objects -vH
    du -sh .git
    
    Show the PowerShell (Windows) version
    PowerShell (Windows)
    git count-objects -vH
    "{0:N1} MB" -f ((Get-ChildItem .git -Recurse -File | Measure-Object Length -Sum).Sum / 1MB)
    
  2. List the biggest objects with their filenames

    This is the canonical recipe: enumerate every object, ask for its size, keep the blobs, sort, and take the top few. The fourth column is the path.

    step 2
    git rev-list --objects --all |
      git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
      awk '/^blob/ {print $3, $4}' |
      sort -rn |
      head -20
    
    Show the PowerShell (Windows) version
    PowerShell (Windows)
    git rev-list --objects --all |
      git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
      Where-Object { $_ -like 'blob*' } |
      ForEach-Object { $p = $_ -split ' '; [PSCustomObject]@{ Size = [long]$p[2]; Path = $p[3] } } |
      Sort-Object Size -Descending | Select-Object -First 20
    
  3. Check whether the file still exists

    Often the culprit was deleted long ago and only survives in history. That's precisely why the repository never shrank when it was removed.

    step 3
    git log --all --oneline -- "**/big-file.psd" | head
    ls -la big-file.psd 2>/dev/null || echo "not in the working tree - history only"
    
  4. Purge the worst offenders from history

    Work on a fresh clone. Strip by size or by path, then force-push and have everyone re-clone.

    step 4
    git clone --mirror . ../repo-backup.git
    pip install git-filter-repo
    
    git filter-repo --strip-blobs-bigger-than 25M
    # or by path:
    git filter-repo --path assets/huge.psd --invert-paths
    

    Every hash after the affected commits changes. Teammates must re-clone, not pull.

  5. Reclaim the space and prevent a repeat

    Garbage collection is what actually frees the disk. Then set up LFS so large binaries never enter history again.

    step 5
    git reflog expire --expire=now --all
    git gc --prune=now --aggressive
    git count-objects -vH
    
    git lfs install
    git lfs track "*.psd" "*.fbx" "*.wav"
    git add .gitattributes
    

Why this works

Git keeps every version of every file forever, and binaries barely compress and change wholesale on each save, so a handful of large assets can dwarf years of source code. Deleting a file adds a commit in which it's absent, but every earlier commit still contains it and a clone downloads all of them. Only rewriting those commits removes the blob, and only garbage collection then reclaims the disk. LFS sidesteps the whole problem by storing a small pointer in Git and the payload elsewhere.

How to stop it happening again

  • Set up Git LFS before committing binary assets, not after.
  • Ignore build output and caches - for Unity that means Library/, Temp/, Build/ and Logs/.
  • Add a pre-commit hook rejecting files over a size threshold.
  • Check git count-objects -vH occasionally so bloat is caught early.

Commands used in this guide

git count-objects

Report how much disk space the repository is using.

git rev-list

List commit hashes matching a range or filter - the engine behind git log.

git cat-file

Print the raw contents or type of any object by its hash.

git filter-repo

Rewrite an entire repository's history - the supported way to purge a leaked secret or a huge file.

git lfs

Store large binary files outside history and keep the repo small.

git gc

Compress the repository and delete unreachable objects.

Still stuck?

Search the full command reference and every other rescue guide — there are 56 of them, covering everything from detached HEAD to force-push disasters.

Browse all guides →

Frequently asked questions

How do I find the largest files in Git history?

Pipe git rev-list --objects --all into git cat-file --batch-check to get each object's type, size and path, filter to blobs, then sort by size. The largest entries are what's inflating your repository, whether or not they still exist in the working tree.

Why is my repo still huge after deleting the big file?

Because deletion only adds a commit where the file is absent. Every earlier commit still contains it, and clones fetch all history. The blob is only gone once you rewrite those commits with filter-repo and run garbage collection.

What size is too big for a Git repository?

There's no hard limit, but clones slow noticeably past about 1 GB and become painful past a few gigabytes. GitHub warns above 1 GB and rejects any single file over 100 MB. Anything binary and over a few megabytes belongs in LFS.

Related rescue guides

← All Git Rescue guides