Git LFS : stocker de gros fichiers dans un dépôt Git
Git LFS (Large File Storage) est une extension de Git qui stocke les gros fichiers binaires sur un serveur séparé et ne place dans le dépôt que de petits fichiers pointeurs. Le clonage devient rapide, l'historique ne gonfle pas, et le travail reste le même qu'avant : git add, commit et push.
Qu'est-ce que Git LFS et à quoi sert-il
Git LFS (Large File Storage) est l'extension officielle de Git pour stocker de gros fichiers : vidéos, maquettes PSD, jeux de données, modèles de réseaux de neurones, assets de jeux. Au lieu du fichier lui-même, le commit contient un pointeur texte d'environ 130 octets, et le contenu part dans un stockage LFS séparé sur le serveur. Au checkout, l'extension remet le vrai fichier dans le répertoire de travail : pour vous, tout ressemble à du Git ordinaire.
Le problème que résout git lfs tient à la conception même de Git. Chaque version de chaque fichier reste pour toujours dans l'historique, et le clonage télécharge tout l'historique. Si vous avez modifié dix fois une vidéo de 200 Mo, le dépôt pèse déjà environ 2 Go, et chaque nouveau développeur télécharge les dix versions même s'il n'a besoin que de la dernière. La compression et les deltas, efficaces sur le texte, sont presque inutiles sur les binaires.
Avec LFS, le clonage ne télécharge que les versions des gros fichiers du commit courant. Les anciennes versions restent sur le serveur et sont récupérées lorsque vous basculez sur un ancien commit.
Comment Git LFS fonctionne en interne
Le mécanisme repose sur les filtres Git clean et smudge. Lorsque vous faites git add sur un fichier suivi par LFS, le filtre clean s'exécute : il place le contenu dans le cache local .git/lfs/objects et transmet un pointeur à l'index. Au checkout, le filtre smudge fait l'inverse : il retrouve l'objet par son hash dans le cache (ou le télécharge depuis le serveur) et écrit le vrai fichier.
Un pointeur ressemble à ceci :
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 209715200
Trois lignes : la version de la spécification, le SHA-256 du contenu et la taille en octets. C'est cela qui est stocké dans l'historique Git, d'où sa légèreté. Lors d'un git push, un hook pre-push s'exécute : les nouveaux objets sont d'abord envoyés via l'API LFS, puis les commits passent par le protocole habituel.
Les fichiers confiés à LFS sont définis dans le fichier .gitattributes à la racine du dépôt. Il est commité avec le code, donc les règles sont les mêmes pour toute l'équipe.
Comment installer Git LFS
Dans Git pour Windows, l'extension est déjà incluse dans l'installateur. Sous macOS et Linux, on l'installe via un paquet :
# macOS (Homebrew)
brew install git-lfs
# Debian / Ubuntu
sudo apt install git-lfs
# Fedora
sudo dnf install git-lfs
Après l'installation, exécutez une fois par utilisateur :
git lfs install
La commande inscrit les filtres LFS dans le ~/.gitconfig global et installe les hooks dans le dépôt courant si vous êtes dedans. Pour vérifier que tout est en place : git lfs version ; la configuration détaillée (adresse du serveur, chemins du cache) s'affiche avec git lfs env.
Commencer à suivre de gros fichiers
Scénario type pour un nouveau projet :
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "models/**"
git add .gitattributes
git add design/banner.psd
git commit -m "Ajouter la maquette de bannière via LFS"
git push origin main
Les guillemets autour du motif sont obligatoires : sans eux, le shell développe lui-même *.psd en liste de fichiers du dossier courant, et la règle ne sera pas la bonne. Après git lfs track, une ligne apparaît dans .gitattributes :
*.psd filter=lfs diff=lfs merge=lfs -text
L'attribut -text désactive la conversion des fins de ligne, qui corromprait un fichier binaire. L'ordre compte : d'abord la règle track, ensuite le git add du fichier. Si le fichier a été ajouté normalement avant la règle, il reste dans l'historique comme un blob ordinaire.
Vérifier qu'un fichier est bien dans LFS
git lfs ls-files
4d7a214614 * design/banner.psd
9c1e0b7a3f * video/intro.mp4
git lfs status
git lfs ls-files liste les fichiers du commit courant stockés dans LFS. L'astérisque signifie que le contenu est téléchargé, le tiret que la copie de travail ne contient que le pointeur. git lfs track sans argument affiche les motifs suivis, et git lfs untrack "*.psd" retire une règle.
Cloner et récupérer les fichiers
Un git clone classique gère LFS de façon transparente : si l'extension est installée, les gros fichiers sont téléchargés automatiquement. Si un collègue n'a pas LFS, il verra des pointeurs texte au lieu des images — le symptôme le plus fréquent de « mon PSD contient du texte bizarre ». La solution : installer l'extension et lancer :
git lfs install
git lfs pull
git lfs pull télécharge les objets du commit courant et les place dans le répertoire de travail. Il existe aussi git lfs fetch, qui télécharge seulement dans le cache sans toucher aux fichiers. Avec --all, il récupère les objets de toutes les références, utile pour une sauvegarde complète ou une migration vers un autre serveur.
Cloner sans les gros fichiers
En CI, ou quand seul le code compte, télécharger des gigaoctets d'assets est superflu. Une variable d'environnement désactive le filtre smudge :
GIT_LFS_SKIP_SMUDGE=1 git clone https://example.com/team/game.git
cd game
git lfs pull --include="textures/ui/**"
Le dépôt est cloné avec les pointeurs, puis vous récupérez sélectivement les fichiers utiles avec --include (il existe aussi --exclude). Cela accélère nettement les builds dans les pipelines.
Migrer des fichiers existants vers Git LFS
Situation courante : le dépôt a déjà gonflé, les gros fichiers sont dans l'historique. git lfs track n'agit pas sur le passé — seulement sur les nouveaux commits. Pour réécrire l'historique, utilisez git lfs migrate.
Évaluez d'abord ce qui prend de la place :
git lfs migrate info --everything --top=10
Puis migrez les types voulus dans toutes les branches :
git lfs migrate import --include="*.psd,*.mp4" --everything
git push --force --all
git push --force --tags
La migration réécrit chaque commit où ces fichiers apparaissaient, donc tous les hashes changent. C'est la même chose qu'un rebase de branches publiées : prévenez tous les participants ; après le push forcé, ils devront recloner le dépôt ou réinitialiser leurs branches en dur. Avant la migration, faites une sauvegarde (git clone --mirror).
Si réécrire l'historique est impossible, il existe une option douce : git lfs migrate import --no-rewrite chemin/vers/fichier. Elle crée un nouveau commit qui fait passer les fichiers dans LFS à partir de ce moment. Les anciennes versions restent dans l'historique, mais la croissance du dépôt s'arrête.
Verrouillage de fichiers : éviter les conflits sur les binaires
Deux designers modifient le même PSD — Git ne pourra pas fusionner leurs changements, et le travail de l'un sera perdu. Pour ces fichiers, LFS propose des verrous. Déclarez le type comme verrouillable :
git lfs track "*.psd" --lockable
L'attribut lockable est ajouté à .gitattributes, et ces fichiers passent en lecture seule dans la copie de travail tant que vous ne les avez pas verrouillés :
git lfs lock design/banner.psd
git lfs locks
design/banner.psd anna ID:123
# après le push des modifications
git lfs unlock design/banner.psd
Tant que le fichier est verrouillé, un push de modifications de ce fichier par une autre personne est refusé. Les verrous sont gérés par le serveur : ils fonctionnent sur les grands hébergeurs Git, mais peuvent manquer sur un serveur maison. Un administrateur peut lever le verrou d'un autre avec git lfs unlock --force.
Où sont stockés les objets LFS et combien ça coûte
Les objets LFS vivent sur un serveur qui implémente l'API LFS. Les hébergeurs Git populaires et les solutions self-hosted la prennent en charge, ainsi que des serveurs dédiés. Les hébergeurs cloud imposent des limites de stockage et de bande passante LFS, qui varient selon le service et l'offre — vérifiez les conditions actuelles de votre plateforme avant d'y déposer des centaines de gigaoctets de données.
Attention : la bande passante est comptée à chaque téléchargement. Un CI qui clone le dépôt avec ses fichiers LFS à chaque commit peut épuiser le quota plus vite que les humains. Mettez .git/lfs en cache entre les builds ou utilisez GIT_LFS_SKIP_SMUDGE.
En local, le cache grossit aussi. La commande git lfs prune supprime les anciens objets déjà présents sur le serveur et inutiles pour les commits actuels et récents.
Quand Git LFS convient, et quand non
| Situation | LFS adapté ? | Commentaire |
|---|---|---|
| Assets de jeu, maquettes, audio, vidéo | Oui | Le cas classique : des binaires modifiés souvent |
| Modèles de ML et jeux de données moyens à côté du code | Oui, en surveillant les quotas | Pour de très gros volumes, des outils spécialisés de versionnage de données sont plus pratiques |
| Artefacts de build compilés | Non | Leur place est dans un registre d'artefacts ou les releases, pas dans Git |
| Dépendances (node_modules, vendor) | Non | Elles sont installées par le gestionnaire de paquets ; ajoutez-les au .gitignore |
| Gros fichiers texte (dumps SQL, CSV) | Ça dépend | Git stocke efficacement le texte en deltas ; LFS se justifie si les fichiers sont énormes et quasi illisibles en diff |
| Secrets et clés privées | Jamais | LFS ne chiffre pas les données, ce n'est pas un coffre à secrets |
Erreurs fréquentes et comment les corriger
La copie de travail contient un pointeur texte au lieu du fichier
LFS n'est pas installé ou le clone a été fait avec GIT_LFS_SKIP_SMUDGE=1. Exécutez git lfs install et git lfs pull.
Un fichier est entré dans l'historique sans passer par LFS
La règle track a été ajoutée après git add. Si le commit n'est pas encore poussé, retirez le fichier de l'index (git rm --cached fichier), vérifiez que la règle figure dans .gitattributes et ajoutez-le de nouveau. S'il est déjà poussé — git lfs migrate import. git lfs fsck --pointers aide à repérer ces fichiers.
Le push est refusé à cause de la taille d'un fichier
Beaucoup d'hébergeurs limitent la taille d'un objet en Git classique. Un message du type « this exceeds the file size limit » signifie que le fichier aurait dû passer par LFS. Réécrivez le dernier commit ou l'historique comme décrit plus haut — un simple commit « supprimer le fichier » ne suffit pas, le fichier reste dans les commits précédents.
Après git lfs migrate, tout est cassé chez les collègues
Leurs branches locales reposent sur les anciens hashes. Le plus sûr est de recloner le dépôt ; s'il reste du travail non poussé, transférez-le par cherry-pick sur les nouvelles branches.
Aide-mémoire des commandes Git LFS
| Commande | Ce qu'elle fait |
|---|---|
git lfs install | Configure les filtres et les hooks |
git lfs track "*.ext" | Ajoute un motif dans .gitattributes |
git lfs untrack "*.ext" | Retire un motif |
git lfs ls-files | Fichiers LFS du commit courant |
git lfs pull | Télécharger et placer les objets |
git lfs fetch --all | Télécharger dans le cache les objets de toutes les références |
git lfs migrate import --include="..." --everything | Migrer des fichiers de l'historique vers LFS |
git lfs lock / unlock / locks | Gestion des verrous |
git lfs prune | Purger le cache local des anciens objets |
git lfs env | Diagnostic de la configuration |
Conclusion
Git LFS sort les gros fichiers binaires de l'historique vers un stockage séparé et ne laisse dans les commits que des pointeurs légers. La règle d'or : configurer git lfs track avant le premier commit de gros fichiers, commiter .gitattributes et surveiller les quotas de l'hébergeur. Si les fichiers sont déjà dans l'historique, git lfs migrate vous aidera, mais c'est une réécriture d'historique avec toutes ses conséquences. Le travail sur l'historique, le rebase et les autres outils avancés de Git sont pratiqués dans le cours Git.
Questions fréquentes
Git LFS est-il gratuit ?
L'extension elle-même est open source et gratuite. Vous pouvez en revanche payer le stockage et la bande passante chez l'hébergeur Git si vous dépassez les limites gratuites de votre offre.
À partir de quelle taille un fichier est-il « gros » pour LFS ?
Il n'y a pas de seuil strict ; on confie généralement à LFS les binaires de quelques mégaoctets et plus, modifiés souvent. Les fichiers texte, même volumineux, sont stockés efficacement par Git sans LFS.
Peut-on abandonner Git LFS et remettre les fichiers dans Git classique ?
Oui, avec git lfs migrate export --include="*.psd" --everything, qui réécrit l'historique dans l'autre sens. Il faut ensuite retirer les règles de .gitattributes et faire un push forcé.
git diff fonctionne-t-il sur les fichiers LFS ?
Git affiche la modification du pointeur, pas du contenu, car les fichiers sont binaires. Pour les images et documents, on compare avec des outils externes.
Chaque membre de l'équipe a-t-il besoin de LFS ?
Oui, sinon un membre sans l'extension aura des pointeurs au lieu des fichiers dans sa copie de travail, et ses commits risquent d'ajouter de gros fichiers en dehors de LFS.
Ce sujet est traité en détail avec de la pratique dans le cours « Git de zéro à développeur confirmé ».
Voir le cours