Après plusieurs semaines de compilations continues sur un Mac dans le cloud, git fetch peut rester rapide tandis que les changements de branche, le calcul des bases de fusion et le parcours des objets ralentissent progressivement. Le réseau est rarement en cause. Le problème vient le plus souvent d’un dépôt persistant qui a accumulé de nombreux objets libres, des fichiers pack fragmentés, des références distantes obsolètes et des verrous de maintenance laissés par des opérations interrompues. Supprimer directement .git puis recréer le clone est une solution simple, mais elle fait perdre le cache d’objets existant et ne fait que reporter le problème au cycle suivant.
Une approche plus fiable consiste à traiter la maintenance du dépôt comme une tâche indépendante : commencer par mesurer son état, exécuter ensuite les opérations progressives sous exclusion mutuelle, puis vérifier la connectivité des objets. La procédure ci-dessous convient aussi bien aux espaces de travail fixes qu’aux nœuds de compilation utilisant plusieurs worktrees.
Établir une référence comparable pour le dépôt
Ne commencez pas par examiner la taille totale du répertoire. Le nombre d’objets Git, leur organisation et leur accessibilité sont des indicateurs bien plus pertinents. Dans le dépôt, consignez les résultats des commandes suivantes :
git count-objects -vH
git rev-parse --git-dir
git rev-parse --git-common-dir
git for-each-ref --format='%(refname)' refs/remotes | wc -l
find "$(git rev-parse --git-common-dir)/objects/pack" -name '*.pack' | wc -l
Une valeur count élevée indique la présence de nombreux objets libres. Une augmentation continue de packs montre que les tâches successives produisent sans cesse de petits packs. Avec des worktrees, la maintenance doit cibler le répertoire commun renvoyé par git rev-parse --git-common-dir. Il ne suffit pas d’examiner le fichier pointeur .git du worktree courant.
Il est recommandé d’enregistrer dans un journal texte ordinaire les valeurs count, in-pack, packs et size-pack avant et après chaque maintenance. Ne jugez pas la réussite uniquement d’après la baisse de l’espace disque utilisé : la mise à jour du graphe des commits peut ne presque rien libérer tout en accélérant le parcours de l’historique et la recherche des bases de fusion.
Privilégier les tâches progressives au nettoyage agressif
Les tâches de maintenance Git peuvent être exécutées séparément. Sur un nœud de compilation persistant, on commence généralement par activer le graphe des commits, le regroupement des objets libres et le repaquetage progressif :
git config maintenance.strategy incremental
git maintenance run \
--task=commit-graph \
--task=loose-objects \
--task=incremental-repack
Le graphe des commits accélère les recherches d’accessibilité dans l’historique. L’index multi-pack évite à Git de parcourir chaque pack individuellement. Le repaquetage progressif fusionne quant à lui les objets par étapes, ce qui évite qu’une récupération complète monopolise trop de temps et d’espace temporaire en une seule opération.
N’utilisez pas
git gc --prune=nowcomme tâche planifiée courante. La suppression immédiate élimine la période de grâce prévue pour la récupération et peut entrer en conflit avec des processus concurrents qui conservent encore des références vers d’anciens objets.
Même après une suppression massive de branches, conservez d’abord la période de grâce par défaut. N’envisagez une récupération plus poussée qu’après avoir vérifié qu’aucune compilation, extraction, opération de rebase, mise à jour de sous-module ou tâche d’archivage n’est en cours.
Gérer séparément les références distantes
Les branches de suivi distantes qui ne sont jamais nettoyées élargissent le périmètre des parcours. Commencez par prévisualiser le résultat, puis lancez le nettoyage :
git remote prune origin --dry-run
git remote prune origin
Ces commandes traitent uniquement les références de suivi distantes. Elles ne remplacent pas la récupération des objets et ne suppriment pas les branches de développement locales. Si un script de compilation dépend d’une référence déjà supprimée du dépôt distant, corrigez d’abord le script au lieu de conserver indéfiniment une référence obsolète.
Isoler les compilations et la maintenance avec un verrou atomique
Les tâches de maintenance et de compilation doivent partager le même verrou au niveau du dépôt. Sur un même système de fichiers, mkdir est atomique et constitue donc un mécanisme de verrouillage simple :
common_dir="$(git rev-parse --git-common-dir)"
lock_dir="$common_dir/maintenance.lock"
if ! mkdir "$lock_dir" 2>/dev/null; then
printf '%s\n' "maintenance skipped: repository is busy"
exit 0
fi
trap 'rmdir "$lock_dir"' EXIT INT TERM
git maintenance run \
--task=commit-graph \
--task=loose-objects \
--task=incremental-repack
Le point d’entrée de la compilation doit lui aussi vérifier ou acquérir ce même verrou. Un verrou posé uniquement par le script de maintenance ne sert à rien. Plusieurs worktrees ne doivent pas créer chacun un verrou dans leur propre répertoire de travail, puisqu’ils partagent la même base d’objets.
Le répertoire de verrouillage peut contenir l’identifiant du processus et son heure de démarrage afin de faciliter les vérifications manuelles. Ne le supprimez toutefois pas uniquement parce que son horodatage paraît ancien. Utilisez d’abord ps pour vérifier si le processus existe encore, puis recherchez une éventuelle exécution de git pack-objects, git index-pack ou git maintenance.
Vérifier les index et la connectivité des objets
Un code de sortie nul de la commande de maintenance signifie seulement que celle-ci s’est terminée. Il ne garantit pas que le dépôt peut être réutilisé sans risque pour les compilations. Exécutez au minimum ces trois types de vérification :
git commit-graph verify
git multi-pack-index verify
git fsck --connectivity-only
Les contrôles peuvent être intégrés au pipeline selon le tableau suivant :
Si une vérification échoue, ne commencez pas par une récupération plus agressive. Préservez les éléments de diagnostic, notamment la sortie des commandes, la version de Git, le chemin du répertoire d’objets commun et l’identifiant du commit de la dernière compilation réussie. En cas d’objet manquant, vous pouvez le récupérer depuis un dépôt distant fiable. Si la restauration reste impossible, isolez l’ancien répertoire et créez un nouveau clone au lieu de multiplier les tentatives de suppression dans le répertoire existant.
Intégrer la maintenance au cycle de vie du nœud
La fréquence de maintenance doit dépendre du volume de modifications du dépôt, et non d’un intervalle fixe en minutes commun à tous les projets. Un monorepo recevant de nombreux commits peut exécuter une maintenance progressive chaque jour après la dernière tâche. Pour un projet moins actif, le déclenchement peut reposer sur l’évolution du nombre d’objets libres et de packs. Vérifiez également l’espace disque disponible avant l’exécution, car les anciens et les nouveaux packs coexistent temporairement pendant le repaquetage.
Sur les Mac cloud de VMOak, il est recommandé de placer le script de maintenance dans un répertoire d’exploitation en lecture seule situé hors du dépôt, puis de laisser l’ordonnanceur lui transmettre le chemin cible. Le script ne doit pas lire un fichier homonyme présent dans une branche du projet, afin qu’une modification ordinaire du code ne puisse pas réécrire la logique de maintenance. Si un nœud héberge plusieurs dépôts, verrouillez et vérifiez chacun d’eux séparément. L’échec d’un dépôt ne doit pas déclencher le nettoyage des autres.
La validation finale ne doit pas se limiter à constater que « l’espace utilisé a diminué ». Effectuez une mise à jour depuis le dépôt distant, extrayez le commit cible, recherchez une base de fusion et lancez une préparation de compilation en lecture seule, puis comparez les journaux avant et après la maintenance pour vérifier que les opérations courantes n’ont pas régressé. La maintenance Git devient ainsi une opération de nœud vérifiable et auditable, plutôt qu’une commande de suppression lancée dans l’urgence lorsque l’espace disque vient à manquer.
Questions fréquentes
Peut-on lancer la maintenance Git pendant une compilation ?
Évitez de la lancer en parallèle d’un checkout, d’un rebase ou d’un empaquetage. Utilisez un verrou atomique par dépôt et attendez que l’espace de travail soit inactif.
Pourquoi éviter une tâche planifiée git gc --prune=now ?
La suppression immédiate retire la marge de récupération et peut viser des objets encore utilisés par un processus concurrent. Le recompactage incrémental est plus prudent.
Quels contrôles effectuer après la maintenance ?
Vérifiez le commit-graph, l’index multi-pack et la connectivité des objets, puis consignez le nombre de packs, d’objets libres et l’espace occupé.
Choisissez un Mac dans le cloud pour vos builds, automatisations ou créations à distance
Comparez les configurations M4 16GB et M4 Pro 64GB, puis vérifiez la durée de location et les nœuds disponibles avant de commander.