Git LFS (Large File Storage)
Scopri Git LFS per tenere file binari di grandi dimensioni fuori dalla cronologia del repository usando puntatori leggeri. Configurazione e comandi.
Cos'è Git LFS
Git LFS (Large File Storage) è un'estensione open-source di Git che mantiene i file binari di grandi dimensioni — video, dataset, risorse grafiche, arte per videogiochi — fuori dalla cronologia di Git. Invece di archiviare un file da 500 MB nel repository, Git LFS salva un piccolo puntatore testuale e conserva il contenuto reale in un archivio LFS separato. Il risultato: i cloni rimangono veloci e il repository rimane leggero, anche quando il progetto contiene gigabyte di risorse.
Questo capitolo illustra quando usare LFS, come installarlo e tracciare i file, cosa contiene effettivamente un puntatore, i comandi più comuni, il blocco dei file per i binari non unibili, e le insidie più frequenti.
Perché i file di grandi dimensioni danneggiano Git
Git è progettato per il testo e memorizza l'intera cronologia di ogni file. Archivia inoltre i file per contenuto: quando un binario cambia, Git di solito conserva l'intera nuova copia anziché una piccola differenza, perché i binari non si prestano a un diff pulito. Effettuare il commit di un binario di grandi dimensioni più volte significa che ogni clone deve scaricare ogni versione per sempre, anche quelle di cui nessuno ha bisogno. La cronologia si gonfia, i cloni diventano lenti e i push vanno in timeout. Git LFS aggira questo problema versionando un piccolo puntatore al posto del contenuto pesante.
Ricorri a LFS quando i file sono grandi e cambiano nel tempo — sorgenti grafiche, risorse compilate, dataset, audio e video. Per i file che non richiedono alcun versionamento, escludili completamente dal repository con .gitignore.
Configurazione
Prima installa Git, poi installa l'estensione LFS. Sulla maggior parte dei sistemi Git LFS è distribuito separatamente (brew install git-lfs, apt install git-lfs, oppure tramite l'installer da git-lfs.com). Abilitalo una volta sola per macchina:
git lfs installUpdated Git hooks.
Git LFS initialized.Indica a LFS quali file gestire tramite i pattern di tracciamento. Questo scrive le regole in .gitattributes:
git lfs track "*.psd"
git lfs track "*.mp4"
git add .gitattributes.gitattributes deve essere committato affinché tutti i collaboratori ricevano le stesse regole. Da questo momento in poi, i file corrispondenti vengono gestiti automaticamente da LFS. Esegui commit e push normalmente:
git add design.psd
git commit -m "Add hero design source"
git pushGit carica il puntatore nel repository e il contenuto binario nell'archivio LFS. Con un nuovo clone, Git LFS si inserisce automaticamente e scarica il contenuto reale per il commit estratto.
Come appare un puntatore
Nel repository, il file tracciato viene sostituito da un piccolo puntatore testuale che registra l'hash e la dimensione del contenuto:
version https://git-lfs.github.com/spec/v1
oid sha256:9af1c2a3b4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f7
size 471859200Le tre righe contengono la versione della specifica, l'id oggetto SHA-256 del contenuto (oid) e la dimensione in byte. Questo è l'intero ingombro nella cronologia di Git — poche centinaia di byte indipendentemente dalle dimensioni della risorsa. Quando qualcuno estrae il file, Git LFS usa questo puntatore per recuperare il contenuto reale su richiesta.
Comandi principali
| Comando | Descrizione |
|---|---|
git lfs install | Abilita LFS per l'utente corrente (da eseguire una volta). |
git lfs track "<pattern>" | Inizia a gestire i file corrispondenti al pattern tramite LFS. |
git lfs untrack "<pattern>" | Smette di gestire un pattern. |
git lfs ls-files | Elenca i file attualmente tracciati da LFS. |
git lfs status | Mostra quali file LFS sono in stage o modificati. |
git lfs pull | Scarica il contenuto LFS per il checkout corrente. |
git lfs fetch | Scarica gli oggetti LFS senza aggiornare la working tree. |
git lfs prune | Elimina i file LFS vecchi e non referenziati dalla memoria locale. |
git lfs migrate | Riscrive la cronologia esistente per spostare i file grandi in LFS. |
Per verificare cosa sta effettivamente gestendo LFS, elenca i file tracciati:
git lfs ls-files9af1c2a3b4 * design.psd
1c0ffee5d6 * intro.mp4Ogni riga mostra l'id oggetto abbreviato, un * quando il contenuto reale è presente localmente (- se è estratto solo il puntatore), e il percorso del file.
Blocco dei file
I binari come .psd o .fbx non possono essere uniti — se due persone modificano lo stesso file, uno dei due set di modifiche viene perso. Git LFS aggiunge il blocco dei file in modo che un membro del team possa riservare un file prima di modificarlo:
git lfs lock images/banner.psd
git lfs locks
git lfs unlock images/banner.psdContrassegna un pattern come bloccabile in .gitattributes per renderlo di sola lettura finché non viene bloccato, prevenendo modifiche accidentali:
git lfs track "*.psd" --lockableIl blocco richiede il supporto del server (GitHub e GitLab lo forniscono).
Spostare file esistenti in LFS
Il tracciamento riguarda solo i file committati dopo l'aggiunta della regola. I file già presenti nella cronologia rimangono in Git come binari completi. Per spostarli, riscrivi la cronologia con git lfs migrate:
git lfs migrate import --include="*.mp4"Questo riscrive i commit, modificandone quindi gli hash — coordina con il tuo team ed esegui un force-push successivamente, come per qualsiasi riscrittura della cronologia.
Cose da sapere
- Il supporto del server è obbligatorio. GitHub, GitLab e Bitbucket forniscono tutti LFS, spesso con quote di spazio e banda che possono generare costi. Un repository può superare la quota LFS anche se la dimensione Git rimane piccola.
- Tutti devono avere l'estensione. Chiunque cloni il repository deve avere Git LFS installato, altrimenti vedrà il testo del puntatore invece del file reale. Se ciò accade, installare LFS ed eseguire
git lfs pullrisolve il problema. - I puntatori sono normali oggetti Git. Branching, merging e diffing del puntatore funzionano normalmente; LFS sostituisce il contenuto reale solo al momento del checkout.