Résolution des problèmes de performance causés par les fichiers volumineux dans Git
Diagnostiquez les dépôts Git lents causés par des fichiers volumineux, choisissez Git LFS avec précaution et nettoyez l'historique sans surprendre votre équipe.
Résolution des problèmes de performance causés par les fichiers volumineux dans Git
Les fichiers volumineux nuisent à Git d'une manière facile à ignorer jusqu'à ce que le dépôt devienne pénible à utiliser. Une seule vidéo, archive, dump de base de données ou fichier de conception peut ne pas sembler dangereux lorsqu'on l'ajoute. Le problème commence lorsque ce fichier change plusieurs fois. Git conserve l'historique, et chaque clone doit transporter cet historique.
Le symptôme est généralement vague au début. git clone prend plus de temps que prévu. git fetch semble lent sur le Wi-Fi d'un hôtel. Les tâches CI passent trop de temps à vérifier le dépôt avant même de construire. Les développeurs commencent à utiliser d'anciens clones locaux parce qu'un nouveau clone est agaçant. C'est le moment d'inspecter le dépôt au lieu de dire à tout le monde d'être patient.
Confirmer que les fichiers volumineux sont le problème
Commencez par des vérifications simples :
du -sh .git
git count-objects -vH
du -sh .git vous indique le poids de la base de données du dépôt local. git count-objects -vH montre les objets non compressés et la taille du pack. Si la taille du pack est grande par rapport à l'arborescence source réelle, l'historique transporte probablement d'anciens fichiers lourds.
Pour trouver les fichiers volumineux dans le checkout actuel :
find . -path ./.git -prune -o -type f -size +10M -print
Cela montre seulement ce qui existe maintenant. Un dépôt peut être lent à cause d'un fichier supprimé il y a des mois. Pour inspecter l'historique, Git LFS fournit un rapport utile même avant toute migration :
git lfs migrate info --everything --above=10MB
Si Git LFS n'est pas installé, vous pouvez toujours enquêter avec les commandes internes de Git, mais la commande ci-dessus est souvent la vue la plus directe pour ce problème spécifique.
Décider ce qui appartient à Git
Tous les fichiers volumineux ne sont pas une erreur. Un petit ensemble d'actifs binaires stables peut être acceptable. Un dépôt pour du code d'infrastructure ne doit pas contenir d'images de machines virtuelles, de sauvegardes de bases de données, d'exports clients ou d'artefacts de construction. Un dépôt de jeu peut légitimement contenir des actifs artistiques et audio, mais ces fichiers nécessitent généralement Git LFS ou un système d'actifs séparé.
Une règle pratique est la suivante : Git est excellent pour le texte source et les petits fichiers de support. Git est mauvais pour les blobs binaires qui changent fréquemment. Si le fichier ne peut pas être examiné de manière significative dans un diff et qu'il change souvent, il ne devrait probablement pas vivre comme un objet Git normal.
Les candidats courants pour Git LFS incluent :
*.psd
*.ai
*.mp4
*.mov
*.wav
*.zip
*.uasset
*.fbx
*.blend
Soyez prudent avec les motifs d'images larges. Suivre chaque *.png dans LFS peut être utile pour un dépôt axé sur la conception, mais peut être agaçant pour une application web avec de nombreuses petites icônes. Les motifs doivent correspondre aux fichiers qui causent réellement des problèmes.
Utiliser Git LFS pour les futurs fichiers volumineux
Git LFS stocke un petit fichier pointeur dans Git et conserve le contenu volumineux dans le stockage LFS. L'historique Git normal reste plus léger, tandis que les utilisateurs obtiennent toujours le fichier réel dans l'arborescence de travail lorsque LFS le télécharge.
Installez-le et initialisez-le :
git lfs install
Suivez les motifs de fichiers dont vous avez réellement besoin :
git lfs track "*.psd"
git lfs track "*.mp4"
git add .gitattributes
git commit -m "Suivre les fichiers de conception et vidéo volumineux avec Git LFS"
Le fichier .gitattributes est important. Validez-le pour que tout le monde utilise les mêmes règles LFS.
Ensuite, ajoutez les fichiers normalement :
git add demo.mp4
git commit -m "Ajouter une vidéo de démonstration du produit"
git push origin main
Un collaborateur doit installer Git LFS avant de travailler avec le dépôt. S'il clone sans support LFS, il peut voir des fichiers pointeurs au lieu des actifs réels jusqu'à ce qu'il installe LFS et exécute :
git lfs pull
Vérifiez également la politique de stockage et de bande passante de votre hébergeur Git. Git LFS résout le gonflement des objets Git, mais ne rend pas les actifs volumineux gratuits à stocker ou à transférer.
Migrer l'historique existant
Activer LFS aujourd'hui ne corrige pas automatiquement les commits d'hier. Si une archive de 700 Mo a été validée puis supprimée, elle peut encore vivre dans l'historique. Nettoyer cela nécessite de réécrire l'historique.
La réécriture de l'historique modifie les ID de commit. Toute personne ayant un clone existant doit se resynchroniser avec précaution, et les pull requests ouvertes peuvent nécessiter un rebase ou une recréation. Faites-le dans une fenêtre de maintenance et faites d'abord une sauvegarde miroir :
git clone --mirror [email protected]:ORG/REPO.git repo-backup.git
Ensuite, travaillez dans un nouveau clone. Assurez-vous que l'arborescence de travail est propre :
git status
Inspectez ce qui serait migré :
git lfs migrate info --everything --above=10MB
Migrez par motif lorsque c'est possible :
git lfs migrate import --everything --include="*.psd,*.mp4,*.zip"
Ou migrez les fichiers au-dessus d'un seuil si le dépôt a de nombreux fichiers volumineux inconnus :
git lfs migrate import --everything --above=10MB
Examinez le résultat avant de pousser :
git log --oneline --decorate -5
git lfs ls-files
git status
git lfs migrate info --everything --above=10MB
Si la migration a fait ce que vous attendiez, poussez les branches et les tags réécrits délibérément :
git push --force-with-lease origin main
git push --force-with-lease origin --tags
Pour un dépôt avec de nombreuses branches actives, décidez quelles branches sont importantes. Vous n'avez peut-être pas besoin de réécrire chaque branche abandonnée, mais toute branche contenant encore les objets volumineux peut alourdir le dépôt distant.
Après une réécriture de l'historique
Dites précisément à vos coéquipiers ce qui a changé. L'instruction la plus propre est souvent de recloner. Si des personnes ont du travail local, elles doivent d'abord le sauvegarder :
git status
git branch my-work-before-lfs-migration
git fetch origin
git rebase origin/main
Pour les clones locaux désordonnés, recloner est moins risqué que d'essayer de réparer chirurgicalement l'ancien historique.
Le stockage distant peut ne pas rétrécir instantanément. Les fournisseurs d'hébergement conservent les objets inaccessibles pendant un certain temps, et certains nécessitent un support ou une maintenance du dépôt avant que les chiffres de stockage ne soient mis à jour. Localement, vous pouvez élaguer les anciens objets après avoir été sûr que la migration est bonne :
git reflog expire --expire=now --all
git gc --prune=now --aggressive
N'exécutez pas les commandes de nettoyage comme substitut à une révision. Elles rendent les anciens objets locaux plus difficiles à récupérer.
Prévenir le même problème à l'avenir
Ajoutez une vérification pre-commit ou pre-receive si de gros fichiers accidentels continuent d'apparaître. Un hook pre-commit local peut avertir les développeurs avant qu'ils ne valident un artefact volumineux. Une règle côté serveur est plus forte car elle protège le dépôt partagé même lorsque quelqu'un saute les hooks locaux.
Une vérification locale simple pourrait rejeter les fichiers au-dessus d'une taille choisie à moins qu'ils ne soient déjà suivis par LFS. Le seuil exact dépend du projet. Un site de documentation et un projet de jeu ne devraient pas utiliser la même limite.
Corrigez également la source des fichiers. Si CI crée dist/, target/, des rapports de couverture, des archives ou des captures d'écran dans le dépôt, ajoutez les bonnes entrées à .gitignore :
dist/
target/
coverage/
*.log
*.zip
N'ignorez pas les fichiers aveuglément. Assurez-vous que les chemins ignorés sont des sorties générées, pas des entrées source.
Quand LFS n'est pas la réponse
Git LFS n'est pas un magasin d'artefacts universel. Les sorties de construction appartiennent généralement à un registre de paquets, un stockage d'objets, un actif de version ou un magasin d'artefacts CI. Les dumps de base de données appartiennent à un stockage de sauvegarde. Les grands ensembles de données peuvent nécessiter un outil de versionnement de données ou un workflow de stockage séparé.
Le but n'est pas de cacher chaque gros fichier à Git. Le but est de garder le dépôt assez rapide pour que les gens puissent cloner, créer des branches, récupérer et réviser sans lutter contre l'outil.
Un bon nettoyage laisse trois choses : des règles .gitattributes claires pour les fichiers qui appartiennent à LFS, des règles .gitignore pour les fichiers qui ne devraient jamais être validés, et une courte note d'équipe expliquant comment les clones existants doivent se resynchroniser. C'est ce qui empêche le correctif de devenir un nettoyage ponctuel que vous répétez le trimestre suivant.