Home/Engineer/Git / CI·CD/Complete Git LFS Guide — Ver…
Git / CI·CDIntermediatelinuxmacoswindowsgitgit-lfslarge-files

Complete Git LFS Guide — Version Control for Large Files

How Git Large File Storage (LFS) works, plus installation, tracking patterns with git lfs track, .gitattributes management, history migration, partial checkout, and repository size control—everything you need to handle large files in Git.

Contents
  1. What is Git LFS?
  2. Installation
  3. Specifying files to track — git lfs track
  4. Checking tracking status
  5. Migrating existing history
  6. Partial checkout — saving bandwidth
  7. LFS vs ordinary Git
  8. Repository size and cleanup
  9. Troubleshooting
  10. .gitattributes best practices
  11. Summary

What is Git LFS?

Git is optimized for tracking changes in text source code. Commit large files—images, video, design originals, datasets, binaries—as-is, and every version piles up in the .git history. The repository balloons to several GB, and clone and fetch become extremely slow. Once a large file is committed, it stays in history forever even if you delete it later.

Git LFS (Large File Storage) is an extension that solves this. The real content of large files lives in a separate LFS store; the Git repository only commits a pointer file (a few dozen bytes of text) that points to that content.

CODE
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345678

On checkout, Git reads the pointer and downloads the real file from the LFS server. History stays light, and you only fetch the versions you need.


Installation

Bash
# macOS
brew install git-lfs

# Debian / Ubuntu
sudo apt install git-lfs

# RHEL / Rocky
sudo dnf install git-lfs

# check
git lfs version

After installing, initialize LFS once per user account (once per machine).

Bash
git lfs install

This command registers LFS filter/smudge/clean hooks in your global Git config.


Specifying files to track — git lfs track

Inside the repository, you specify which files LFS should handle using patterns.

Bash
#
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.zip"

#
git lfs track "assets/models/**"

# check
git lfs track

This command creates or updates a .gitattributes file at the repository root.

CODE
*.psd  filter=lfs diff=lfs merge=lfs -text
*.mp4  filter=lfs diff=lfs merge=lfs -text
*.zip  filter=lfs diff=lfs merge=lfs -text

You must commit .gitattributes. Without it, collaborators and CI treat those files as ordinary Git files and LFS will not work.

Bash
git add .gitattributes
git commit -m "chore: track binary assets with Git LFS"

After that, adding, committing, and pushing files like *.psd is handled by LFS automatically.

Bash
git add design/cover.psd
git commit -m "feat: add cover artwork"
git push origin main

Checking tracking status

Bash
# LFS file list
git lfs ls-files

#
# 4d7a214614 * design/cover.psd
# a91f0c8e2b - assets/intro.mp4

# save·LFS
git lfs env

# file file check
git lfs pointer --file=design/cover.psd

In ls-files, * means the real file is present in the working tree; - means only the pointer is present.


Migrating existing history

If large files were already committed the ordinary way, git lfs track alone will not clean up past commits. Rewrite history with git lfs migrate.

Bash
# *.psd, *.zip LFS
git lfs migrate import --include="*.psd,*.zip"

# /
git lfs migrate import --include="*.psd" --everything

migrate import rewrites every commit hash (history rewrite). If the branch is shared, agree with collaborators first, and push with git push --force-with-lease. Always back up before you start.

To reverse LFS and convert files back to ordinary Git objects, use git lfs migrate export --include="*.psd".


Partial checkout — saving bandwidth

You can avoid downloading every LFS file in a large repository.

Bash
# LFS file clone
GIT_LFS_SKIP_SMUDGE=1 git clone <repo-url>

#
git lfs pull --include="design/*.psd"

#
git config lfs.fetchexclude "assets/raw/**"

# file
git config lfs.fetchrecentcommitsdays 7

LFS vs ordinary Git

ItemOrdinary Git commitGit LFS
What goes into the repoEntire file (every version)Pointer text only
Clone speedSlows as history growsFast — only needed versions
Diff of large filesAlmost impossiblePointer comparison (metadata)
History sizeKeeps growingStays light
Best forText sourceImages, video, binaries, datasets

Repository size and cleanup

LFS objects are cached locally in .git/lfs/objects. You can prune old objects.

Bash
# LFS
git lfs prune

#
git lfs prune --dry-run

# LFS
git lfs fetch --all

Hosting services such as GitHub and GitLab have separate quotas for LFS storage and bandwidth (e.g. GitHub Free: 1 GB storage / 1 GB bandwidth per month). Check costs in advance for large datasets.


Troubleshooting

SymptomCause / fix
After clone, files appear as pointer textgit lfs install was not run → run it, then git lfs pull
LFS does not work for collaborators.gitattributes not committed → commit and share it
batch response: 403 on pushLFS permission or quota issue. Check token and capacity
Large files already committed as ordinary Git objectsConvert with git lfs migrate import
smudge filter lfs failedNetwork/auth problem. Bypass with GIT_LFS_SKIP_SMUDGE=1, then git lfs pull

.gitattributes best practices

CODE
#
*.psd   filter=lfs diff=lfs merge=lfs -text
*.ai    filter=lfs diff=lfs merge=lfs -text
*.mp4   filter=lfs diff=lfs merge=lfs -text
*.mov   filter=lfs diff=lfs merge=lfs -text

# archive /
*.zip       filter=lfs diff=lfs merge=lfs -text
*.tar.gz    filter=lfs diff=lfs merge=lfs -text
*.onnx      filter=lfs diff=lfs merge=lfs -text
*.bin       filter=lfs diff=lfs merge=lfs -text

The -text attribute treats the file as binary and prevents line-ending conversion (CRLF↔LF). Always attach it to LFS-tracked files.


Summary

TaskCommand
Machine init (once)git lfs install
Set tracking patterngit lfs track "*.psd"
List tracked filesgit lfs ls-files
Convert existing historygit lfs migrate import --include="*.zip"
Clone pointers onlyGIT_LFS_SKIP_SMUDGE=1 git clone
Fetch only what you needgit lfs pull --include="..."
Prune local cachegit lfs prune

Git LFS fills Git’s weakness with text-oriented storage by treating large files as lightweight pointers. The essentials: always commit .gitattributes, migrate existing large files, and watch your hosting quotas.

#git#git-lfs#large-files#version-control
Editorial note

AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us

Topic-related official docs (auto-linked · not per-claim sources)Git documentation ↗pgvector repository ↗

Questions & answers

Ask a question about this guide. We'll review and reply.