Remove a huge file that's bloating your repository
I committed a large file and my push is rejected — how do I remove it?
Short answer
If it's still the last commit, git reset --soft HEAD~1 and re-commit without it. If it's further back, purge it from history with git filter-repo --strip-blobs-bigger-than. Going forward, route large binaries through Git LFS.
git reset --soft HEAD~1
git restore --staged path/to/huge-file.psd
git commit -m "Commit without the large asset"
Fixes it when the large file is in the most recent commit
Does this match your situation?
- GitHub rejects your push: 'file exceeds GitHub's file size limit of 100 MB'.
- Cloning the repository takes an extremely long time.
- A .psd, .fbx, video, database dump or build artifact got committed.
- The .git folder is enormous compared to your actual project.
Step-by-step fix
Find what's actually taking up the space
Before rewriting anything, confirm which objects are the problem. This lists the largest blobs in your history by size.
step 1git count-objects -vH git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print $3, $4}' | sort -rn | head -10Show the PowerShell (Windows) version
PowerShell (Windows)git count-objects -vH git verify-pack -v .git/objects/pack/*.idx | Sort-Object { [int]($_ -split '\s+')[2] } -Descending | Select-Object -First 10If it's in the last commit, just redo it
By far the easiest case. Undo the commit, drop the offending file from the staging area, and commit again without it.
step 2git reset --soft HEAD~1 git restore --staged assets/huge-texture.psd echo "*.psd" >> .gitignore git add .gitignore git commit -m "Add textures, excluding source PSD files"If it's deeper in history, purge it
A file committed and then deleted still lives in every earlier commit and still gets cloned. Removing it properly means rewriting those commits. Clone a backup first.
step 3git clone --mirror . ../repo-backup.git pip install git-filter-repo # remove one path from all of history: git filter-repo --path assets/huge-texture.psd --invert-paths # or strip everything over 50 MB: git filter-repo --strip-blobs-bigger-than 50MForce-push and have the team re-clone
The rewrite changed every affected commit hash, so the remote needs the new history and existing clones are stale.
step 4git remote add origin <url> # filter-repo drops remotes deliberately git push --force --all git push --force --tagsTeammates must re-clone. Pulling would drag the large objects straight back in.
Set up Git LFS so it doesn't recur
LFS keeps large binaries on a separate store and commits only a small pointer file, which is the correct long-term answer for art, audio and 3D assets.
step 5git lfs install git lfs track "*.psd" git lfs track "*.fbx" git lfs track "*.wav" git add .gitattributes git commit -m "Track binary assets with Git LFS"
Why this works
Git stores a complete compressed copy of every version of every file, forever. That's ideal for text, where each revision compresses down to a small delta, and terrible for binaries, which barely compress and change wholesale every save. Deleting the file in a later commit doesn't help, because clones fetch all history by default and the old objects come along. Only rewriting the commits that contained the blob actually removes it — and LFS avoids the problem entirely by storing a 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 imported caches — for Unity that means Library/, Temp/, Build/ and Logs/.
- Add a pre-commit hook that rejects files over a size threshold.
- Run git count-objects -vH occasionally to catch bloat early.
Commands used in this guide
git filter-repoRewrite an entire repository's history - the supported way to purge a leaked secret or a huge file.
git lfsStore large binary files outside history and keep the repo small.
git resetMove the current branch pointer, optionally rewriting the index and your files.
git restoreThrow away working-directory changes or unstage files (the modern, clearer replacement for checkout).
git pushUpload your commits to the remote repository.
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 remove a large file from Git history?
Use git filter-repo --path <file> --invert-paths to strip it from every commit, or --strip-blobs-bigger-than 50M to remove everything over a size threshold. Then force-push, and have everyone re-clone rather than pull.
Why is my repository still huge after deleting the file?
Because deleting a file only adds a commit where it's absent — every earlier commit still contains it, and clones download all history. The blob is only gone once you rewrite those commits and run garbage collection.
What is Git LFS and when should I use it?
Git Large File Storage replaces big binaries with small pointer files and keeps the real data on a separate server. Use it for art, audio, video, 3D models and any asset over a few megabytes — and set it up before those files are committed, since retrofitting means rewriting history.
GitHub rejected my push for a file over 100 MB — what now?
GitHub blocks any single file over 100 MB regardless of your repo size. Remove the file from the commits that contain it (reset if it's the latest, filter-repo if it's older), then either exclude it or track it with Git LFS before pushing again.
Related rescue guides
I committed a secret — how do I remove it from Git history?
Rotate the secret first — that's the only step that genuinely protects you. Then purge it from history with git filter-repo (or the BFG Repo-Cleaner) and force-push. Deleting the file in a new commit does nothing, because the old commit still contains it and is still fetchable.
Read the fix →Always fixableWhy is .gitignore not working for files that are already tracked?
.gitignore only applies to untracked files. Once a file has been committed, Git keeps tracking it no matter what the ignore rules say. Remove it from the index with git rm --cached <file> — that stops tracking while leaving the file on your disk.
Read the fix →Always fixableHow do I undo the last commit but keep my work?
git reset --soft HEAD~1 removes the commit and leaves every change staged, ready to recommit. Use --mixed (the default) if you also want the changes unstaged, and only use --hard if you genuinely want the work destroyed. If the commit is already pushed, revert it instead of resetting.
Read the fix →Always fixableHow do I undo git add without losing my changes?
git restore --staged <file> removes a file from the staging area and leaves your edits completely untouched. The older equivalent is git reset HEAD <file>. Neither one touches the contents of your file, so this is a zero-risk operation.
Read the fix →