La performance de fetch et push dépend de l'efficacité de négociation, de la taille de transfert et du calcul côté serveur. Chacun a ses leviers, et les bons diffèrent par taille de repo.
git maintenance (Git 2.31+) est le remplaçant moderne orienté tâches pour gc --auto. Il exécute des tâches spécifiques (commit-graph, prefetch, incremental-repack, loose-objects, pack-refs, gc) sur des plannings adaptés à chacune, en arrière-plan, sans bloquer vos commandes interactives.
git gc effectue la maintenance : repacke les objets loose, élague les non atteignables au-delà de la fenêtre d'expiration, empaquette les refs loose dans packed-refs, expire les reflogs, et écrit commit-graph et MIDX là où c'est configuré.
git gc traditionnel exécute git repack -ad, réécrivant tous les objets dans un packfile. Sur un repo de plusieurs gigaoctets, c'est des heures de CPU et IO. Le repacking géométrique (Git 2.32+) l'évite en maintenant une série de packs dont les tailles suivent une progression géométrique.
Des opérations comme clone, fetch et gc doivent calculer "quels objets sont atteignables depuis ces commits ?" — un parcours de graphe qui touche chaque objet atteignable. Les bitmaps d'atteignabilité stockent cette réponse comme bitmaps compressés.
Un repo avec de nombreux packfiles doit chercher dans chacun pour localiser un objet — une recherche binaire par pack. Avec des dizaines ou centaines de packs (commun dans les repos actifs utilisant le repack géométrique), ce coût O(packs × log objets) s'accumule. Le multi-pack-index (MIDX) consolide tous les indexes de pack en une seule recherche binaire.
git log -- path/to/file doit en principe parcourir chaque commit, faire un diff par rapport à son parent et émettre ceux qui ont touché path/to/file. Sur les gros repos cela est dominé par les comparaisons de tree. Les filtres Bloom de chemins changés (Git 2.27+) accélèrent dramatiquement.
De nombreuses opérations Git doivent répondre "le commit X est-il atteignable depuis Y ?" ou "quelle est la base de merge ?" Naïvement cela signifie parcourir le graphe de commits depuis des lectures brutes d'objets — lent sur les gros repos. Le fichier commit-graph précalcule les pointeurs parents, les numéros de génération et (optionnellement) les filtres Bloom.
Où il vit
Git ancien : .git/objects/info/commit-graph. Git moderne : .git/objects/info/commit-graphs/.
Trace2 (introduit dans Git 2.22) est la fonctionnalité de tracing structuré intégrée dans Git. Elle émet des événements de début/fin de région, du tracking de processus enfants et des informations de timing dans un schéma stable.
Git était à l'origine réglé pour le noyau Linux — gros pour 2005 mais petit pour aujourd'hui. Les repos modernes peuvent contenir des millions de fichiers, des centaines de gigaoctets d'historique et des dizaines de milliers de refs. Beaucoup d'opérations Git étaient O(taille de l'arbre) ou O(historique) par défaut.