Accélérer Git : Techniques essentielles d'optimisation des performances

Accélérez Git en réduisant le coût du clonage, en utilisant Git LFS à bon escient, en élaguant les références obsolètes, en ignorant les fichiers générés et en appliquant un checkout partiel.

Accélérer Git : Techniques essentielles d'optimisation des performances

Un Git lent a généralement une cause concrète : trop d'historique, trop de fichiers non suivis, de gros objets binaires, des analyses coûteuses du système de fichiers ou une latence réseau. Avant de blâmer Git lui-même, vérifiez quelle opération est lente et ce qu'elle essaie de lire ou de télécharger.

L'optimisation des performances de Git fonctionne mieux lorsque vous adaptez la solution au symptôme. Un clonage CI lent nécessite une réponse différente d'un git status lent dans un arbre de travail volumineux.

Comprendre les causes des performances lentes de Git

Commencez par les causes courantes :

  • Un long historique avec de nombreux fichiers et références.
  • De gros fichiers binaires commités directement dans Git.
  • Des sorties de build, des dossiers de dépendances ou des logs laissés non ignorés dans l'arbre de travail.
  • De nombreuses branches de suivi à distance et tags obsolètes.
  • Des liens réseau lents vers le dépôt distant.
  • D'anciennes versions de Git manquant des améliorations récentes en matière de maintenance et de checkout partiel.

Exécutez la commande lente avec intention. Si git clone est lent, examinez la taille de l'historique et le transfert réseau. Si git status est lent, examinez la taille de l'arbre de travail, les fichiers ignorés et le comportement du système de fichiers. Si git fetch est lent, examinez les références distantes, les tags et les objets modifiés.

Réduire le coût du clonage et du fetch

Pour les jobs CI, les déploiements et les inspections en lecture seule, vous n'avez souvent pas besoin de tout l'historique.

Utilisez un clone superficiel :

git clone --depth <nombre> <url_du_dépôt>

Par exemple, pour cloner uniquement les 10 derniers commits :

git clone --depth 10 https://github.com/exemple/repo.git

Pour les jobs CI qui ne construisent que le commit actuel, --depth 1 est souvent suffisant. Pour le travail des développeurs, un clone complet est généralement moins surprenant car des commandes telles que git log profond, le checkout de tags anciens et certains rebases ont besoin de plus d'historique.

Si vous avez déjà un clone superficiel et avez besoin de plus d'historique, approfondissez-le :

git fetch --deepen=50 origin

Ou convertissez-le en clone complet :

git fetch --unshallow origin

Pour des besoins de données partielles, les versions plus récentes de Git prennent également en charge les filtres de clone partiel tels que --filter=blob:none, mais utilisez-les uniquement lorsque votre hébergeur Git et votre flux de travail les prennent bien en charge :

git clone --filter=blob:none https://github.com/exemple/gros-repo.git

Garder les gros fichiers en dehors de l'historique Git normal

Les gros binaires sont l'un des moyens les plus rapides de ralentir Git. Les images, vidéos, archives, fichiers de conception et fichiers de modèles ne se compressent ou ne se différencient souvent pas bien.

Utilisez Git LFS pour les gros actifs qui appartiennent vraiment au dépôt :

git lfs install
git lfs track "*.psd"
git lfs track "assets/*.mp4"
git add .gitattributes
git commit -m "Suivre les gros actifs avec Git LFS"

Git LFS affecte les commits futurs après la mise en place des règles de suivi. Si quelqu'un a déjà commité de gros fichiers dans l'historique Git normal, les supprimer de l'arbre actuel ne suffit pas. Vous pourriez avoir besoin d'une réécriture coordonnée de l'historique avec un outil tel que git lfs migrate import ou git filter-repo.

Pour les artefacts de build générés, la meilleure réponse n'est généralement pas LFS. Ne les commitez pas. Ajoutez-les plutôt à .gitignore :

node_modules/
dist/
coverage/
*.log

Nettoyer les références et objets locaux

Les branches de suivi à distance obsolètes ajoutent du désordre et peuvent ralentir les commandes qui listent ou inspectent les références. Éliminez-les lors du fetch :

git fetch --prune

Supprimez les branches locales qui sont déjà fusionnées et dont vous n'avez plus besoin :

git branch --merged
git branch -d ancienne-branche-fonctionnalité

Laissez Git exécuter la maintenance :

git maintenance run

Sur les anciens flux de travail, git gc est toujours utile :

git gc

Évitez les commandes de nettoyage agressives sauf si vous savez pourquoi vous en avez besoin. Par exemple, faire expirer les reflogs peut rendre plus difficile la récupération après une mauvaise réinitialisation.

Rendre git status moins coûteux

git status doit inspecter l'arbre de travail. Si votre répertoire de projet contient des milliers de fichiers générés ou de dépendances, le statut peut devenir bruyant et lent.

Utilisez .gitignore pour les fichiers que Git ne doit pas prendre en compte. Si un fichier est déjà suivi, .gitignore n'empêchera pas Git de le suivre ; vous devez d'abord le supprimer de l'index :

git rm --cached chemin/vers/fichier-généré

Pour les très grands dépôts où vous n'avez besoin que d'une partie de l'arbre, le checkout partiel peut aider :

git sparse-checkout init --cone
git sparse-checkout set services/api docs

Cela ne conserve que les chemins sélectionnés dans votre arbre de travail. C'est utile dans les monorepos, mais votre équipe doit documenter les chemins partiels attendus afin que les développeurs ne manquent pas les fichiers dont ils ont besoin.

Séparer le fetch de l'intégration

git pull récupère puis intègre les modifications avec merge ou rebase, selon la configuration. Lorsqu'un dépôt est volumineux ou qu'une branche a divergé, il est souvent plus clair de d'abord récupérer :

git fetch origin
git log --oneline HEAD..origin/main
git merge origin/main

Cela ne réduit pas en soi le transfert réseau. Cela vous donne le contrôle avant de modifier votre branche de travail.

En pratique

Utilisez des clones superficiels pour les jobs de courte durée, Git LFS pour les gros actifs, .gitignore pour les fichiers générés, l'élagage pour les références obsolètes et le checkout partiel pour les grands arbres où vous n'avez besoin que d'un sous-ensemble. Gardez Git à jour, mais n'utilisez pas d'outils d'intégrité tels que git fsck comme correctif de performance sauf si vous soupçonnez une corruption du dépôt.

Lorsque Git semble lent, notez la commande exacte et où le temps est passé : transfert réseau, traitement des objets ou analyse de l'arbre de travail. Ce détail indique généralement la bonne optimisation.