Git LFS — Large Files
Large binary files ke bina LFS ke Git kaa sabse bada dosh hai.
Git was designed for TEXT files with small, line-based changes. It stores full snapshots and uses delta compression to save space. This works brilliantly for source code — a 10-line change in a 500-line file produces a tiny diff.
Binary files (images, videos, ML models, PDFs, compiled artifacts) are completely different. They don't have "lines" — Git cannot delta-compress them effectively. Every modification stores a COMPLETE new copy in the repository.
A 500MB file modified 10 times = 5GB in your .git directory, even though you only need the latest version. The repository grows with every binary change and never shrinks.
Cloning a repo with years of binary history downloads ALL versions, even old ones you'll never use. A 2.5GB repo takes 30+ minutes to clone on a decent connection.
Git operations become painfully slow: git status scans large files, git push uploads massive objects, git clone downloads everything.
GitHub rejects files larger than 100MB by default. Push a 200MB file and you get an error — your team is blocked.
# The large file problem
# Team adds a 500MB design file to the repo
cp ~/design-v1.psd assets/design.psd
git add assets/design.psd
git commit -m "add design file"
git push origin main
# Designer updates the file 5 times
cp ~/design-v2.psd assets/design.psd && git add . && git commit -m "design v2"
cp ~/design-v3.psd assets/design.psd && git add . && git commit -m "design v3"
cp ~/design-v4.psd assets/design.psd && git add . && git commit -m "design v4"
cp ~/design-v5.psd assets/design.psd && git add . && git commit -m "design v5"
# Now the repo is 2.5GB (5 versions x 500MB)
du -sh .git/
# 2.5G
# New developer clones the repo
git clone https://github.com/company/app.git
# Downloads ALL 2.5GB — even the 4 old versions they don't need!
# Takes 30+ minutes
# GitHub rejects the push:
# remote: error: File assets/design.psd is 500.00 MB;
# this exceeds GitHub's file size limit of 100.00 MBGit LFS (Large File Storage) replaces large files with tiny pointer files in the repository. The pointer file contains metadata (SHA-256 hash, file size) but NOT the actual content.
The actual file content is stored on a separate LFS server (GitHub LFS, GitLab LFS, etc.). When you checkout a commit, LFS automatically downloads the correct version of the file.
When you clone, you only download the pointer files — this is fast! LFS files are downloaded on demand when you check them out. Old versions of LFS files are NOT downloaded during clone — only the version you check out.
This keeps the .git directory small and clone times fast, even for repos with gigabytes of binary assets.
The pointer file is approximately 130 bytes — compared to a 500MB binary file, that is a reduction of over 99.9999%.
# What Git LFS does:
# WITHOUT LFS:
# .git/objects/ contains the FULL 500MB file
# Clone downloads ALL versions (2.5GB total)
# WITH LFS:
# .git/objects/ contains a tiny pointer file (130 bytes)
# Clone downloads only pointers (a few KB)
# Actual files downloaded only when you check them out
# The pointer file looks like this:
cat assets/design.psd
# version https://git-lfs.github.com/spec/v1
# oid sha256:abc123def456...
# size 524288000
# When you checkout or cat the file, LFS transparently
# downloads the real content from the LFS serverSetting up Git LFS is straightforward, but order matters — you must configure tracking BEFORE adding large files.
Step 1: Install Git LFS — brew install git-lfs (macOS), apt-get install git-lfs (Ubuntu), or choco install git-lfs (Windows).
Step 2: Initialize LFS in your repo — git lfs install sets up the clean/smudge filters and hooks.
Step 3: Track file types — git lfs track "*.psd" stores the rule in .gitattributes. You can track by extension, directory, or specific filenames.
Step 4: Commit .gitattributes — this ensures all team members use LFS for these files. Without this commit, LFS tracking won't work for others.
Step 5: Add large files normally — LFS automatically intercepts them. git add and git commit work exactly the same. LFS handles the rest transparently.
# Step 1: Install Git LFS
brew install git-lfs # macOS
apt-get install git-lfs # Ubuntu/Debian
choco install git-lfs # Windows
# Step 2: Initialize LFS in your repository
cd my-project
git lfs install
# Updated git hooks. Git LFS initialized.
# Step 3: Track large file types
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "*.mp4"
git lfs track "assets/**"
git lfs track "models/*.pkl" # ML model files
# Step 4: Commit the .gitattributes
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text
# *.zip filter=lfs diff=lfs merge=lfs -text
# *.mp4 filter=lfs diff=lfs merge=lfs -text
git add .gitattributes
git commit -m "chore: configure Git LFS"
# Step 5: Add large files normally
cp ~/design.psd assets/design.psd
git add assets/design.psd
git commit -m "add design file"
# LFS automatically handles the file!
# Step 6: Push (LFS uploads to LFS server)
git push origin main
# Uploading LFS objects: 100% (1/1), 500 MBIf you already committed large files without LFS, you must migrate them. This is possible but expensive — it rewrites history.
git lfs migrate import --include="*.psd" converts existing files to LFS pointers across all commits where those files appear.
This REWRITES HISTORY — all commit hashes that touched those files will change. Every team member must re-clone the repository. Old clones become incompatible.
Use --include-ref=main to only migrate files on specified branches. Use --everything to migrate all branches and tags.
The migration process can take a long time for repos with many large files and extensive history.
ALWAYS backup your repository before migrating. Once history is rewritten, there is no undo.
# Scenario: You already committed large files without LFS
# Step 1: Check what large files exist
git lfs migrate info --include="*"
# *.psd 2.5 GB 5 files
# *.zip 1.2 GB 3 files
# Step 2: Migrate specific file types
git lfs migrate import --include="*.psd,*.zip"
# Rewriting history... done.
# Step 3: Verify
git lfs ls-files
# abc1234 - assets/design.psd
# def5678 - assets/archive.zip
# Step 4: Force push (history was rewritten)
git push --force --all
# Step 5: Team members must re-clone
# Old clones have the old (non-LFS) history
# Migrate only on main branch
git lfs migrate import --include="*.psd" --include-ref=main
# Migrate everything (all branches)
git lfs migrate import --include="*.psd" --everything
# BACKUP FIRST!
cp -r my-project my-project-backup
GitHub LFS has bandwidth and storage quotas that you must monitor. The free tier includes 1GB storage + 1GB/month bandwidth.
Additional storage costs $5/month per 50GB. Additional bandwidth costs $5/month per 50GB. Every clone, checkout, and CI build consumes LFS bandwidth.
Best practices for LFS:
- Don't track files that change frequently — each version consumes storage and bandwidth.
- Use
.gitattributesto track only necessary large files. - Consider external storage (S3, GCS) for very large assets that exceed your LFS budget.
- Use
git lfs fetch --recentto download only recent versions and save bandwidth. - Lock files to prevent concurrent editing of binary assets that can't be merged.
# Check LFS usage
git lfs env
# List tracked LFS files
git lfs ls-files
# Fetch LFS objects (if missing)
git lfs fetch --all # download all versions
git lfs fetch --recent # only recent versions (saves bandwidth)
git lfs pull # fetch + checkout
# Lock files for editing (prevents conflicts)
git lfs lock assets/design.psd
git lfs locks # see all locks
# assets/design.psd sai (ID: 123)
# Edit, commit, push, then unlock
git lfs unlock assets/design.psd
# Prune old LFS objects (free disk space)
git lfs prune
# Removes old versions not referenced by recent commits
# .gitattributes best practices
# Track specific binary types
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
# Track specific directories
assets/images/** filter=lfs diff=lfs merge=lfs -text
models/** filter=lfs diff=lfs merge=lfs -text
# DO NOT track these (they change too often)
# *.pdf - use external storage instead
# *.docx - use Google Docs instead
git lfs lock assets/design.psd to lock binary files you are editing. This prevents other team members from editing the same binary file simultaneously, which would cause unresolvable merge conflicts. Lock, edit, commit, push, unlock.Lo kar liya — Key Points:
- ✅ Git was designed for text files and struggles with large binary files (images, videos, ML models)
- ✅ Every modification to a binary file stores a full new copy, making repos grow rapidly
- ✅ Git LFS replaces large files with tiny pointer files in the repo, storing actual content on an LFS server
- ✅ Set up LFS tracking BEFORE adding large files using git lfs track and committing .gitattributes
- ✅ git lfs migrate import converts existing large files to LFS pointers, but rewrites history
- ✅ GitHub LFS free tier includes 1GB storage and 1GB bandwidth per month
- ✅ Use git lfs lock to prevent concurrent editing of binary files that can't be merged
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login