W3docs

Git LFS (Large File Storage)

Learn Git LFS (Large File Storage) to keep big binary assets out of your repository history using lightweight pointers. Setup and commands included.

What is Git LFS

Git LFS (Large File Storage) is an open-source Git extension that keeps large binary files — videos, datasets, design assets, game art — out of your Git history. Instead of storing a 500 MB file in the repository, Git LFS stores a tiny text pointer and keeps the real content in a separate LFS store. The result: clones stay fast and the repository stays small, even when the project ships gigabytes of assets.

This chapter covers when to reach for LFS, how to install and track files, what a pointer actually contains, the everyday commands, file locking for un-mergeable binaries, and the gotchas that trip people up.

Git LFS replacing a large file with a small pointer, with content in a separate store

Why large files hurt Git

Git is built for text and stores the full history of every file. It also stores files by content: when a binary changes, Git usually keeps the entire new copy rather than a small diff, because binaries don't diff cleanly. Commit a big binary a few times and every clone must download every version of it forever — even versions nobody needs. History balloons, clones crawl, and pushes time out. Git LFS sidesteps this by versioning a small pointer instead of the heavy content.

Reach for LFS when files are large and change over time — design sources, compiled assets, datasets, audio and video. For files that never need versioning at all, keep them out of the repo entirely with .gitignore instead.

Setup

First install Git itself, then install the LFS extension. On most systems Git LFS ships separately (brew install git-lfs, apt install git-lfs, or the installer from git-lfs.com). Enable it once per machine:

git lfs install
Updated Git hooks.
Git LFS initialized.

Tell LFS which files to manage by tracking patterns. This writes rules into .gitattributes:

git lfs track "*.psd"
git lfs track "*.mp4"
git add .gitattributes

.gitattributes should be committed so every collaborator gets the same rules. From now on, matching files are stored through LFS automatically. Commit and push as usual:

git add design.psd
git commit -m "Add hero design source"
git push

Git uploads the pointer to the repository and the binary content to the LFS store. On a fresh clone, Git LFS hooks in automatically and downloads the real content for the checked-out commit.

What a pointer looks like

In the repository, the tracked file is replaced by a small text pointer that records the content's hash and size:

version https://git-lfs.github.com/spec/v1
oid sha256:9af1c2a3b4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f7
size 471859200

The three lines are the spec version, the content's SHA-256 object id (oid), and the byte size. That's the entire footprint in Git history — a few hundred bytes no matter how big the asset is. When someone checks out the file, Git LFS uses this pointer to fetch the real content on demand.

Common commands

CommandDescription
git lfs installEnables LFS for your user (run once).
git lfs track "<pattern>"Starts managing files matching a pattern via LFS.
git lfs untrack "<pattern>"Stops managing a pattern.
git lfs ls-filesLists the files currently tracked by LFS.
git lfs statusShows which LFS files are staged or modified.
git lfs pullDownloads the LFS content for the current checkout.
git lfs fetchDownloads LFS objects without updating the working tree.
git lfs pruneDeletes old, unreferenced LFS files from local storage.
git lfs migrateRewrites existing history to move large files into LFS.

To confirm what LFS is actually managing, list the tracked files:

git lfs ls-files
9af1c2a3b4 * design.psd
1c0ffee5d6 * intro.mp4

Each line shows the short object id, a * when the real content is present locally (- if only the pointer is checked out), and the path.

File locking

Binaries like .psd or .fbx cannot be merged — if two people edit the same one, one set of changes is lost. Git LFS adds file locking so a teammate can claim a file before editing it:

git lfs lock images/banner.psd
git lfs locks
git lfs unlock images/banner.psd

Mark a pattern as lockable in .gitattributes to flag it read-only until locked, which prevents accidental edits:

git lfs track "*.psd" --lockable

Locking needs server support (GitHub and GitLab provide it).

Moving existing files into LFS

Tracking only affects files committed after you add the rule. Files already in history stay in Git as full binaries. To move them, rewrite history with git lfs migrate:

git lfs migrate import --include="*.mp4"

This rewrites commits, so it changes their hashes — coordinate with your team and force-push afterward, just like any history rewrite.

Things to know

  • Server support is required. GitHub, GitLab, and Bitbucket all provide LFS, often with storage and bandwidth quotas that can incur cost. A repository can exceed its LFS quota even while its Git size stays small.
  • Everyone needs the extension. Anyone cloning the repository must have Git LFS installed, or they will see the pointer text instead of the real file. If that happens, installing LFS and running git lfs pull fixes it.
  • Pointers are normal Git objects. Branching, merging, and diffing the pointer work normally; LFS only swaps in the real content at checkout time.

Practice

Practice
How does Git LFS keep repositories small?
How does Git LFS keep repositories small?
Was this page helpful?