Why My Model Wouldn’t Deploy to Hugging Face Spaces (and What Git LFS Actually Does)
Source: Dev.to
What I Tried (and Why It Kept Failing)
When I tried to push the repository, Git rejected it with the following error:
remote: -------------------------------------------------------------------------
remote: Your push was rejected because it contains files larger than 10 MiB.
remote: Please use https://git-lfs.github.com/ to store large files.
remote: See also: https://hf.co/docs/hub/repositories-getting-started#terminal
remote:
remote: Offending files:
remote: - model.pkl (ref: refs/heads/main)
remote: -------------------------------------------------------------------------
To https://huggingface.co/spaces/chloezhoudev/minima
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://huggingface.co/spaces/chloezhoudev/minima'
I could see what Git was complaining about—model.pkl was too large—but I didn’t really understand why this was a problem, or what “Git LFS” actually meant in practice. I had never used it before.
So I followed the instructions in the error message and tried to fix it step‑by‑step.
1️⃣ Install and initialise Git LFS
brew install git-lfs # Install Git LFS (macOS via Homebrew)
git lfs install # Initialise Git LFS and register Git hooks
git lfs version # Confirm Git LFS installation
2️⃣ Track the model file and push
git lfs track "model.pkl"
git add model.pkl
git commit -m "Track model file with Git LFS"
git push
The push failed again—with the exact same error.
3️⃣ Try removing the file from the index
git rm --cached model.pkl
git lfs track "model.pkl"
git commit -m "Store model file using Git LFS"
git push
Same error. 😅
4️⃣ Create an orphan branch
git checkout --orphan clean-main
git add .
git commit -m "Initial deployment with Git LFS model"
git branch -M main
git push -f origin main
This time, the push finally worked.
What I Eventually Learned About Git and Git LFS
Why did Git keep rejecting my pushes?
Hugging Face repos enforce a pre‑receive hook that scans all commits in your push and rejects the push if any commit contains a file larger than 10 MiB.
If a large file is stored as a normal Git blob in any commit, the hook will reject the push, even if you later add LFS tracking.
What does Git LFS actually do?
- Normal Git stores file contents as blob objects. Each file you add is stored (roughly) at its original size in the repository history. For binary files this means the full data is kept in every commit that touches the file.
- Git LFS replaces large files with pointer files (tiny text files) and stores the actual binary data on a dedicated LFS server. When you
git adda file that matches an LFS rule, Git LFS creates a pointer, hands that pointer to Git, and uploads the real file to the LFS store.
Why didn’t git rm --cached help?
git rm --cached model.pkl only removed the file from the index of the current working tree. The large blob was already present in the previous commit(s) that you were trying to push, so the pre‑receive hook still saw a commit containing the oversized blob and rejected the push.
Why did creating an orphan branch fix everything?
git checkout --orphan clean-main started a new history with no previous commits. By adding the files after LFS was set up and committing only once, the repository’s sole commit contained the LFS pointer instead of the large blob. Consequently, the pre‑receive hook saw no oversized blobs and allowed the push.
Key Takeaways
-
Large files must be tracked by LFS before they ever enter the repository history.
Adding LFS tracking after a large file has already been committed does not retroactively rewrite that commit. -
The
.gitattributesfile drives LFS tracking.
Hugging Face Spaces automatically adds a line like:*.pkl filter=lfs diff=lfs merge=lfs -textThis tells Git to treat any
*.pklfile as an LFS object, provided LFS is installed when the file is first added. -
Removing a file from the index does not erase it from history.
To truly get rid of an oversized blob you must rewrite history (e.g., withgit filter-repoor by creating a fresh orphan branch). -
Orphan branches are a quick way to start clean.
When you have a small project and want to guarantee that no large blobs are present, creating an orphan branch after LFS is set up guarantees a clean first commit.
TL;DR
- Install Git LFS before adding any large files.
- Ensure the appropriate pattern is in
.gitattributes. - If you accidentally commit a large file, either rewrite history or start a new orphan branch and recommit with LFS tracking enabled.
Now the model is stored efficiently, the Space deploys without errors, and I finally understand what Git LFS does and why the orphan‑branch trick worked.
What about git rm — cached?
⚠️ Important
git rm --cached only affects future commits. It does not remove files from your existing Git history.
- The command removes the file from the staging area and stops tracking it in upcoming commits, while leaving the file intact in your working directory.
- However, it does nothing to delete the earlier commit where the large file was first added.
Because that original commit still contained model.pkl as a normal Git blob, the problematic file remained in the repository history — and Hugging Face continued to reject the push.
The Fix That Worked
Creating a new branch with no history (git checkout — orphan) fixed everything because it started with a clean slate that had no commits at all.
-
Create an orphan branch
git checkout --orphan new-main -
Add the files (with Git LFS already configured)
git add . git commit -m "Add files with LFS" -
Rename the branch to
mainand force‑pushgit branch -M main git push -f origin main
Warning: Using
--orphanand especiallygit push -fis dangerous if multiple collaborators are using the same branch, because this replaces the branch’s history. In my case, the Space repo was just for deployment, so this was fine, but it’s something to be careful about in team settings.
💡 Bonus: Git LFS Isn’t the Only Option Anymore
Hugging Face now also recommends git‑xet, a newer backend designed specifically for large machine‑learning artifacts.
- Git LFS moves large files out of Git.
- git‑xet rethinks how Git stores large content altogether.
After all that debugging, the model is finally deployed and working as expected. You can try the live demo here.
Thanks for reading. 😊