Lesson 26 of 30
Git stores every version of every file forever — great for a 4KB source file, catastrophic for a 400MB video. Git LFS is the workaround.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Git's whole design assumes files are small and text-based, so it can diff them efficiently and store only what changed. Give it a 200MB video or a 500MB Photoshop file and that assumption breaks: git doesn't diff binaries meaningfully, so every commit that touches the file stores a full new copy in .git. Change the file ten times and you've got roughly ten full copies sitting in history forever — git gc can't help, because nothing about those blobs is actually redundant to git's compression.
The repo doesn't get slower to work in day-to-day, but every clone gets bigger, forever, even if the current working tree only has one version of the file. A repo that's accumulated a few years of design assets can be gigabytes before anyone notices, and there's no clean way to shrink it without rewriting history.
Git LFS (Large File Storage) fixes this by not storing the binary in git at all. Instead, git tracks a tiny pointer file — a few lines of text with a hash and a size — and the actual binary content lives on a separate LFS server, fetched on demand.
git lfs install # one-time, per machine
git lfs track "*.psd" # writes/updates .gitattributes
git add .gitattributes
git add design/hero-banner.psd
git commit -m "add hero banner design"
git lfs track doesn't touch the file — it writes a rule to .gitattributes:
*.psd filter=lfs diff=lfs merge=lfs -text
That's the whole mechanism: any file matching *.psd gets intercepted by git's filter system on add/checkout. What actually lands in the git object database is not the Photoshop file — it's a pointer:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b25ac1729547
size 132239245
git status and git log look completely normal — you'd never know from the CLI that the real 130MB file isn't in .git. Run git lfs ls-files to see which paths are actually LFS-backed, and git lfs pull to fetch the real content into your working tree (a plain git clone on an LFS-enabled repo pulls pointers fast, then LFS content separately — that's why a "small" clone can still take a while).
git lfs install run locally, or their checkouts silently get pointer files instead of real content..gitattributes has to be committed and pushed before anyone else benefits. If you track a pattern locally but never commit .gitattributes, the next person to add a matching file won't get LFS behavior at all — it'll go in as a normal (huge) blob.*.psd today does nothing about the 15 non-LFS .psd blobs already sitting in past commits. Cleaning those out needs git lfs migrate import --include="*.psd" --everything, which rewrites history — same blast radius as any history rewrite (see the force-push lesson).The pointer-file trick is the same idea as a database storing a URL instead of a blob, or a symlink pointing at a real file elsewhere — git's content-addressed object model stays untouched (it's still hashing and diffing small text files), while the actual heavy payload moves to storage that's actually good at serving large binaries.