Git

How to Fix Git Push Failing With "GH001: Large Files Detected" (GitHub 100MB Limit)

4 min read by DebuggedIt

Quick answer

Pushing to GitHub gets rejected because a file in your commit exceeds GitHub's hard 100MB per-file limit. Unlike a warning you can ignore, this is a hard...

Pushing to GitHub gets rejected because a file in your commit exceeds GitHub's hard 100MB per-file limit. Unlike a warning you can ignore, this is a hard server-side rejection β€” GitHub simply won't accept the push until the oversized file is removed from what you're trying to push, including from earlier commits if it was already committed previously.

The Problem

A push that includes a large file fails outright:

$ git push origin main
remote: error: GH001: Large files detected. You may want to try Git Large File Storage.
remote: error: Trace: a1b2c3d4e5f6...
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File assets/demo-video.mp4 is 142.35 MB; this exceeds GitHub's file size limit of 100.00 MB
To github.com:youruser/yourrepo.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'github.com:youruser/yourrepo.git'

Why It Happens

GitHub enforces a hard 100MB limit per file, checked on every push, specifically to protect the performance and storage characteristics of Git repositories, which are fundamentally not designed to handle very large binary files efficiently. This rejection happens regardless of whether the large file is in your most recent commit or buried several commits back in what you're currently pushing β€” GitHub scans every commit included in the push, not just the latest snapshot. Common causes:

  • A large binary asset (a video, a dataset, a compiled build artifact, a database dump) was committed directly without realizing Git isn't well suited to storing it this way.
  • The file was added, then later deleted in a subsequent commit β€” but since Git history is immutable, the large file still exists in the earlier commit and gets included in the push regardless of the deletion.
  • A build process or IDE accidentally committed a generated file (a large log, a cache directory, a compiled binary) that should have been excluded via .gitignore from the start.

The Fix

If the large file is only in your most recent, not-yet-pushed commit, the simplest fix is amending that commit to remove it before pushing at all:

git rm --cached assets/demo-video.mp4
echo "assets/demo-video.mp4" >> .gitignore
git add .gitignore
git commit --amend --no-edit
git push origin main

If the large file was committed several commits back (even if it was later deleted), simply removing it now isn't enough β€” it's still present in the earlier commit's history, and that history is what's actually being rejected. Use git filter-repo to remove it from every commit in your history:

pip install git-filter-repo
git filter-repo --path assets/demo-video.mp4 --invert-paths

This rewrites every commit, removing the file entirely from history rather than just the current snapshot. Since this changes commit hashes throughout your history, you'll need to force-push the rewritten branches:

git push origin --force --all
git push origin --force --tags

Anyone else with a local clone will need to re-clone or hard-reset to the rewritten history, since their existing commits no longer match.

For legitimately large files your project actually needs to version (not just accidentally committed build artifacts), switch to Git LFS going forward, which stores large files outside the normal Git object database while keeping a small pointer file in your actual Git history:

git lfs install
git lfs track "*.mp4"
git add .gitattributes
git add assets/demo-video.mp4
git commit -m "Track video assets with Git LFS"
git push origin main

Going forward, any file matching a tracked pattern is automatically stored via LFS rather than directly in Git's history, avoiding this size limit for legitimate large-file use cases.

Still Not Working?

If you're not sure exactly which commits contain the oversized file after a complex history, search explicitly rather than guessing which commit to target with filter-repo:

git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sort -k3 -n -r | head -20

This lists every object in your repository's entire history sorted by size, largest first, making it easy to confirm exactly which files (and by extension which commits) are responsible for exceeding the limit before you commit to rewriting history to remove them.