# 2. Git LFS for Unity Assets **Target:** Unity 6000.5+. Part of [[Version Control]]. Assumes [[1. Serialization Meta and Gitignore]]. ## Why LFS exists for Unity Git stores every version of every file in history. A 50 MB texture revised twenty times is painful; a 200 MB audio bank without LFS can **block** pushes to GitHub. Git Large File Storage replaces large file contents with small **pointer** files in Git and stores blobs on an LFS server (GitHub hosts this for GitHub remotes). - Project site: https://git-lfs.com/ - GitHub: [About Git LFS](https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-git-large-file-storage) - Configure tracking: [Configuring Git Large File Storage](https://docs.github.com/en/repositories/working-with-files/managing-large-files/configuring-git-large-file-storage) - Hard GitHub limits without LFS: [About large files on GitHub](https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-large-files-on-github) ### GitHub size facts (from GitHub docs; not invented) - Warning around **50 MiB** for regular Git files; **hard block above 100 MiB** without LFS. - Browser uploads capped lower (25 MiB) — irrelevant for normal CLI/Desktop pushes. - Per-file LFS maximums depend on plan (GitHub docs table: Free/Pro **2 GB**, Team **4 GB**, Enterprise Cloud **5 GB** as of the fetched docs). Confirm current plan limits on GitHub’s LFS pages before assuming headroom. - Prefer keeping whole repositories small (GitHub recommends ideally **< 1 GB**, strongly **< 5 GB**). > [!warning] Not verified live > `git lfs install`, `track`, `lock`, and bandwidth quotas were **not** exercised on Enceladus for this note. Run the commands on your machine and check GitHub **Settings → Billing / Packages & Actions / Git LFS** (UI labels vary) for remaining quota. ## Step 1 — Install and enable LFS once per user 1. Install Git LFS from https://git-lfs.com/ (Windows installer, or package manager). Latest published on that site at fetch time was **v3.8.1** — check the site for the current build; do not hard-pin blindly in team docs without re-checking. 2. In any terminal: ```bash git lfs install ``` That registers LFS filters for your user account (once per machine/user). ## Step 2 — Decide what to track **Strong LFS candidates (binary, large, revised often):** | Pattern | Typical content | |---|---| | `*.psd`, `*.psb`, `*.tga`, `*.tif`, `*.tiff` | Source art | | `*.png`, `*.jpg`, `*.jpeg`, `*.exr`, `*.hdr` | Large textures / HDR (optional if small UI icons — see below) | | `*.fbx`, `*.obj`, `*.blend` | Meshes / DCC sources | | `*.wav`, `*.aiff`, `*.mp3`, `*.ogg`, `*.flac` | Audio | | `*.mp4`, `*.mov`, `*.webm` | Video / cutscenes | | `*.dll`, `*.so`, `*.dylib`, `*.a`, `*.bundle` | Native plugins (when you must version them) | | `*.zip`, `*.7z`, `*.rar`, `*.unitypackage` | Archives (prefer not shipping `.unitypackage` in-repo) | **Usually keep in normal Git (text / tiny):** - `.cs`, `.shader`, `.hlsl`, `.compute`, `.json`, `.txt`, `.md` - `.unity`, `.prefab`, `.asset`, `.mat`, `.controller`, `.anim` (YAML after Force Text) — LFS here **defeats** readable diffs and UnityYAMLMerge - `.meta` files — **never** LFS; they are tiny text GUID carriers **Judgment call:** thousands of tiny UI PNGs may be fine in Git; a handful of 8K EXRs belong in LFS. Track by **extension + folder** when mixed. ## Step 3 — Track patterns (writes `.gitattributes`) From the **project root**: ```bash git lfs track "*.psd" git lfs track "*.fbx" git lfs track "*.wav" git lfs track "*.mp4" git lfs track "*.dll" ``` Or lockable binaries (see Step 5): ```bash git lfs track --lockable "*.psd" git lfs track --lockable "*.fbx" ``` **Always commit `.gitattributes`** so every clone shares the same rules ([GitHub configuring LFS](https://docs.github.com/en/repositories/working-with-files/managing-large-files/configuring-git-large-file-storage)): ```bash git add .gitattributes git commit -m "Track large Unity binaries with Git LFS" ``` ### Example `.gitattributes` (illustrative) ```gitattributes # Git LFS — adjust to your art/audio pipeline *.psd filter=lfs diff=lfs merge=lfs -text lockable *.psb filter=lfs diff=lfs merge=lfs -text lockable *.fbx filter=lfs diff=lfs merge=lfs -text lockable *.blend filter=lfs diff=lfs merge=lfs -text *.wav filter=lfs diff=lfs merge=lfs -text *.mp3 filter=lfs diff=lfs merge=lfs -text *.ogg filter=lfs diff=lfs merge=lfs -text *.mp4 filter=lfs diff=lfs merge=lfs -text *.mov filter=lfs diff=lfs merge=lfs -text *.exr filter=lfs diff=lfs merge=lfs -text *.tga filter=lfs diff=lfs merge=lfs -text *.tif filter=lfs diff=lfs merge=lfs -text *.tiff filter=lfs diff=lfs merge=lfs -text # Optional: large textures only under a folder Assets/Art/Textures/HD/**/*.png filter=lfs diff=lfs merge=lfs -text Assets/Art/Textures/HD/**/*.jpg filter=lfs diff=lfs merge=lfs -text # Native plugins (example) *.dll filter=lfs diff=lfs merge=lfs -text *.so filter=lfs diff=lfs merge=lfs -text *.dylib filter=lfs diff=lfs merge=lfs -text ``` Pointer files look like ([About Git LFS](https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-git-large-file-storage)): ```text version https://git-lfs.github.com/spec/v1 oid sha256:4cac19622fc3ada9c0fdeadb33f88f367b541f38b89102a3f1261ac81fd5bcb5 size 84977953 ``` If a teammate clones **without** LFS installed, they only get pointers — broken textures/audio until they install LFS and fetch ([Collaboration with Git LFS](https://docs.github.com/en/repositories/working-with-files/managing-large-files/collaboration-with-git-large-file-storage)). ## Step 4 — Add, commit, push as usual ```bash git add Assets/Art/Hero.psd git commit -m "Add hero PSD (LFS)" git push origin main ``` You should see LFS transfer progress on push. GitHub Desktop also supports LFS clones/pushes (see GitHub Desktop docs linked from the LFS pages). ## Step 5 — Lock vs unlock (caveats) Git LFS can mark patterns **`lockable`**. Intent: exclusive edit of non-mergeable binaries. ```bash # claim git lfs lock Assets/Art/Hero.psd # list git lfs locks # release when done git lfs unlock Assets/Art/Hero.psd ``` Reference: [git-lfs-lock(1)](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-lock.adoc). ### Caveats you must plan for 1. **Server must support locking.** GitHub supports LFS locking for repos that use it; still verify with a test lock on your remote. Locking is **not** a substitute for communication. 2. **Lockable files are often made read-only** in the working tree until locked — artists using DCC tools that refuse read-only files will hit friction. Document the lock → edit → unlock loop. 3. **Locks are social + server-side, not magic.** Someone can still force-unlock (`git lfs unlock --force` where permitted) or edit offline and fight on push. Treat locks like checkouts. 4. **Scenes/Prefabs:** Prefer Prefab isolation and branch discipline ([[4. Conflicts Prefabs and Branching]]) over LFS locks on `.unity` / `.prefab`. Those should stay text + UnityYAMLMerge, not LFS. 5. **Migrating history:** `git lfs track` alone does **not** rewrite old commits. Existing large blobs already in Git need `git lfs migrate` (see git-lfs docs / `git lfs migrate --help`). Migration rewrites history — coordinate with the team. 6. **Bandwidth & storage quotas** are billed/limited on GitHub. Every clone that downloads LFS objects consumes bandwidth. Large binary thrash (re-exporting the same FBX daily) burns quota even with LFS — see [[6. Pitfalls]]. 7. **PRs on github.com** often show the **pointer**, not a binary diff ([Collaboration with Git LFS](https://docs.github.com/en/repositories/working-with-files/managing-large-files/collaboration-with-git-large-file-storage)). Review art locally. ## Step 6 — Verify tracking ```bash git lfs track # patterns git lfs ls-files # files currently pointer-managed git check-attr filter -- Assets/Art/Hero.psd ``` Expect `filter: lfs` for tracked paths. ## When UVCS Smart Locks fit better If your pain is **exclusive checkout of non-mergeable assets** across a mixed artist/engineer team, Unity Version Control’s **Smart Locks** are purpose-built ([Smart Locks](https://docs.unity.com/en-us/unity-version-control/smart-locks)). Compare in [[5. Clients and UVCS Comparison]]. ## Next [[3. UnityYAMLMerge Smart Merge]] — semantic merges for scenes and Prefabs.