Date de la publication : 25 août 2025

Lecture : 14 min

Nouveautés de Git 2.51.0

Découvrez les dernières contributions de l'équipe Git de GitLab et de la communauté Git, notamment les optimisations de performances pour git-push(1) et git-fetch(1).

Le projet Git a récemment publié la version Git 2.51. En raison de l'été dans l'hémisphère nord et d'un développement plus lent, ce cycle de sortie de nouvelles versions a été plus court et a duré 8 semaines (au lieu des 12 semaines habituelles). Passons en revue certaines modifications notables de cette version, notamment les contributions de l'équipe Git de GitLab ainsi que de la communauté Git dans son ensemble.

Optimisations des performances pour git-push(1) et git-fetch(1)

Les commandes git-push(1) et git-fetch(1) permettent aux utilisateurs de synchroniser les dépôts locaux et distants. Une partie de ces commandes consiste à mettre à jour les références dans le dépôt, ce qui peut prendre un temps considérable dans les dépôts comportant de nombreuses références, en particulier pour les utilisateurs qui travaillent avec de grands environnements de développement, des monorepos ou des dépôts avec des pipelines CI/CD étendus.

Les transactions de références Git peuvent inclure plusieurs mises à jour de références, mais elles suivent une approche « tout ou rien ». Si une seule mise à jour dans la transaction échoue, la transaction entière échoue, et aucune des mises à jour de références n'est appliquée. Cependant, les mises à jour de références dans git-push(1) et git-fetch(1) sont autorisées à échouer, ce qui permet aux dépôts de synchroniser un sous-ensemble de références même si un sous-ensemble différent a divergé. Pour faciliter ce comportement, Git crée une transaction distincte pour chaque mise à jour de référence afin que certaines transactions réussissent même si d'autres échouent.

La création d'une transaction distincte par mise à jour entraîne une surcharge opérationnelle importante, car chaque transaction comprend une phase d'initialisation et de finalisation, et vérifie s'il existe des noms de références contradictoires. Le backend « reftable » effectue également un compactage automatique à la fin de chaque transaction. De multiples transactions peuvent ainsi déclencher plusieurs compactages automatiques, ce qui peut augmenter considérablement la latence de la commande.

Dans Git 2.51.0, ces commandes utilisent désormais des mises à jour par lots au lieu de transactions distinctes afin de mettre à jour plusieurs références dans une seule transaction, tout en autorisant certaines mises à jour à échouer. Cette approche élimine le surcoût lié aux initialisations, vérifications et finalisations répétées et supporte mieux la montée en charge du nombre de références à mettre à jour, puisqu'une seule transaction est utilisée. Les performances du backend « reftable » en sont considérablement améliorées, et ce dernier surpasse désormais le backend « files ». Ces améliorations de performances s'appliquent de manière transparente pour les utilisateurs.

Pour git-fetch(1), nous constatons des performances 22x meilleures pour le backend « reftable » et 1,25x meilleures pour le backend « files » lorsque cette commande est utilisée dans un dépôt avec 10 000 références.

Benchmark 1: fetch: many refs (refformat = reftable, refcount = 10000, revision = master)
  Time (mean ± σ):      3.403 s ±  0.775 s    [User: 1.875 s, System: 1.417 s]
  Range (min … max):    2.454 s …  4.529 s    10 runs

Benchmark 2: fetch: many refs (refformat = reftable, refcount = 10000, revision = HEAD)
 Time (mean ± σ):     154.3 ms ±  17.6 ms    [User: 102.5 ms, System: 56.1 ms]
 Range (min … max):   145.2 ms … 220.5 ms    18 runs

Summary
  fetch: many refs (refformat = reftable, refcount = 10000, revision = HEAD) ran
   22.06 ± 5.62 times faster than fetch: many refs (refformat = reftable, refcount = 10000, revision = master)

Benchmark 1: fetch: many refs (refformat = files, refcount = 10000, revision = master)
  Time (mean ± σ):     605.5 ms ±   9.4 ms    [User: 117.8 ms, System: 483.3 ms]
  Range (min … max):   595.6 ms … 621.5 ms    10 runs

Benchmark 2: fetch: many refs (refformat = files, refcount = 10000, revision = HEAD)
  Time (mean ± σ):     485.8 ms ±   4.3 ms    [User: 91.1 ms, System: 396.7 ms]
  Range (min … max):   477.6 ms … 494.3 ms    10 runs

Summary
  fetch: many refs (refformat = files, refcount = 10000, revision = HEAD) ran
   1.25 ± 0.02 times faster than fetch: many refs (refformat = files, refcount = 10000, revision = master)

Pour git-push(1), nous constatons des performances 18x meilleures pour le backend reftable et 1,21x meilleures pour le backend « files » lorsque cette commande est utilisée dans un dépôt avec 10 000 références.

Benchmark 1: push: many refs (refformat = reftable, refcount = 10000, revision = master)
  Time (mean ± σ):      4.276 s ±  0.078 s    [User: 0.796 s, System: 3.318 s]
  Range (min … max):    4.185 s …  4.430 s    10 runs

Benchmark 2: push: many refs (refformat = reftable, refcount = 10000, revision = HEAD)
  Time (mean ± σ):     235.4 ms ±   6.9 ms    [User: 75.4 ms, System: 157.3 ms]
  Range (min … max):   228.5 ms … 254.2 ms    11 runs

Summary
  push: many refs (refformat = reftable, refcount = 10000, revision = HEAD) ran
   18.16 ± 0.63 times faster than push: many refs (refformat = reftable, refcount = 10000, revision = master)

Benchmark 1: push: many refs (refformat = files, refcount = 10000, revision = master)
  Time (mean ± σ):      1.121 s ±  0.021 s    [User: 0.128 s, System: 0.975 s]
  Range (min … max):    1.097 s …  1.156 s    10 runs

Benchmark 2: push: many refs (refformat = files, refcount = 10000, revision = HEAD)
  Time (mean ± σ):     927.9 ms ±  22.6 ms    [User: 99.0 ms, System: 815.2 ms]
  Range (min … max):   903.1 ms … 978.0 ms    10 runs

Summary
  push: many refs (refformat = files, refcount = 10000, revision = HEAD) ran
    1.21 ± 0.04 times faster than push: many refs (refformat = files, refcount = 10000, revision = master)

Ce projet a été mené par Karthik Nayak.

En route vers la version Git 3.0

La dernière version majeure de Git, la version 2.0, a été publiée il y a onze ans déjà. Bien que nous n'ayons pas de calendrier spécifique pour la prochaine version majeure de Git, la version 2.51.0 inclut déjà des décisions concernant Git 3.0.

La planification de la version Git 3.0 nous permet de prévoir et d'implémenter des changements rendant cette version incompatible avec les précédentes et de les communiquer à la communauté Git. En plus de la documentation, Git peut également être compilé avec ces changements incompatibles à des fins de test. Pour en savoir plus, consultez le document BreakingChanges.

La version Git 2.51.0 apporte des changements importants en préparation de Git 3.0.

Reftable comme backend de références par défaut

Dans la version Git 2.45.0, le format « reftable » a été introduit comme nouveau backend pour stocker les références comme les branches ou les tags dans Git, afin de corriger de nombreux problèmes avec le backend « files » existant. Consultez notre guide du débutant sur le fonctionnement du format reftable pour obtenir plus d'informations sur le backend « reftable ».

La version Git 2.51.0 marque le passage à l'utilisation du format « reftable » par défaut dans Git 3.0 pour les dépôts nouvellement créés et configure également le changement d'un feature flag. Le format « reftable » offre les améliorations suivantes par rapport au backend « files » traditionnel :

  • Il est impossible de stocker deux références avec pour seule différence la casse sur des systèmes de fichiers qui ne tiennent pas compte de la casse avec le format « files ». Ce problème est courant sur les systèmes Windows et macOS. Étant donné que le backend « reftable » n'utilise pas de chemins de système de fichiers pour encoder les noms de références, ce problème n'a plus lieu d'être.

  • De même, macOS normalise les noms de chemins qui contiennent des caractères unicode. Vous ne pouvez donc pas stocker deux noms avec des caractères unicode qui sont encodés différemment avec le backend « files », mais ce n'est pas un problème avec le backend « reftable ».

  • La suppression de références avec le backend « files » nécessite que Git réécrive le fichier complet « packed-refs ». Dans les grands dépôts avec de nombreuses références, ce fichier peut facilement faire des dizaines de mégaoctets, voire des gigaoctets. Le backend « reftable » utilise des marqueurs « tombstone » pour les références supprimées et n'a donc pas à réécrire toutes ses données.

  • La maintenance du dépôt avec le backend « files » effectue généralement des repacks tout-en-un des références. Cette approche peut être assez coûteuse, et par conséquent, la maintenance est un compromis entre le nombre de références seules par fichier qui s'accumulent et ralentissent les opérations qui lisent les références, et la compression de ces références non compactées en un seul fichier « packed-refs ». Le backend « reftable » utilise le compactage géométrique après chaque écriture, ce qui amortit les coûts et garantit que le backend est toujours bien entretenu.

  • Les opérations qui écrivent plusieurs références à la fois ne sont pas atomiques avec le backend « files ». Par conséquent, Git peut voir des états intermédiaires lorsqu'il lit des références pendant qu'une transaction de référence est en cours de validation sur le disque.

  • L'écriture de nombreuses références à la fois est un processus lent avec le backend « files », car chaque référence est créée en tant que fichier séparé. Le backend « reftable » fournit des résultats considérablement meilleurs par rapport au backend « files ».

  • Le backend « reftable » utilise un format binaire avec compression de préfixe pour les noms de références. En conséquence, le format utilise moins d'espace par rapport au fichier « packed-refs ».

Ce projet a été mené par Patrick Steinhardt.

SHA-256 comme fonction de hachage par défaut

Le système de contrôle de version Git stocke les objets dans un système de fichiers adressable par contenu. Cela signifie qu'il utilise le hachage d'un objet pour adresser le contenu tel que les fichiers, les répertoires et les révisions, contrairement aux systèmes de fichiers traditionnels, qui utilisent des nombres séquentiels. L'utilisation d'une fonction de hachage présente les avantages suivants :

  • Vérifications faciles de l'intégrité, car un seul bit inversé modifierait complètement le résultat du hachage.

  • Recherche d'objets rapide, car ces derniers peuvent être indexés par leur hachage.

  • Les noms d'objets peuvent être signés, et des tiers peuvent faire confiance au hachage pour adresser l'objet signé et tous les objets qu'il référence.

  • La communication via le protocole Git et les méthodes de communication hors bande disposent d'une chaîne de caractères courte et fiable qui peut être utilisée pour adresser de manière fiable le contenu stocké.

Depuis sa création, Git a utilisé l'algorithme de hachage SHA-1. Cependant, des chercheurs en sécurité ont découvert quelques failles dans cet algorithme, en particulier l'attaque SHAttered, qui montre une collision de hachage SHA-1 réalisable en pratique. Nous sommes passés à l'utilisation d'une implémentation SHA-1 renforcée par défaut depuis Git 2.13.0. Cependant, SHA-1 reste un algorithme de hachage faible, et ce n'est qu'une question de temps avant que des attaques supplémentaires ne diminuent encore davantage sa sécurité.

SHA-256 a été identifié comme le successeur de SHA-1 fin 2018. Git 2.51.0 le marque comme l'algorithme de hachage par défaut à utiliser dans Git 3.0.

Ce projet a été mené par brian m. carlson.

Suppression de git-whatchanged(1)

La commande git-whatchanged(1) montre les logs avec les différences que chaque commit introduit. Bien que cette commande soit maintenant remplacée par git log --raw, elle a été conservée pour des raisons historiques.

Git 2.51.0 oblige les utilisateurs de la commande à utiliser explicitement le flag --i-still-use-this pour identifier tous les utilisateurs qui utilisent encore cette commande dépréciée, et marque également la commande pour suppression dans Git 3.0.

Ce projet a été mené par Junio C Hamano.

git switch et git restore ne sont plus en phase expérimentale

La commande git-checkout(1) peut être utilisée dans plusieurs cas d'utilisation différents. Elle peut être utilisée pour changer la référence courante :

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

$ git checkout next
Switched to branch 'next'
Your branch is up to date with 'origin/next'.

Ou pour restaurer des fichiers :

$ echo "additional line" >> git.c

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   git.c

no changes added to commit (use "git add" and/or "git commit -a")

$ git checkout git.c
Updated 1 path from the index

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Pour les nouveaux utilisateurs de Git, ces différentes possibilités peuvent être source de confusion. Dans Git 2.33.0, elles ont été divisées en deux nouvelles commandes, git-switch(1) et git-restore(1).

La commande git-switch(1) permet aux utilisateurs de basculer vers une branche spécifique :

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

$ git switch next
Switched to branch 'next'
Your branch is up to date with 'origin/next'.

Et la commande git-restore(1) permet aux utilisateurs de restaurer les fichiers de l'arbre de travail :

$ echo "additional line" >> git.c

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   git.c

no changes added to commit (use "git add" and/or "git commit -a")

$ git restore git.c

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Ces deux commandes existent depuis 2019, mais étaient en phase expérimentale. Ce qui signifie que le projet Git ne garantissait pas la compatibilité avec les versions précédentes pour ces commandes, et le comportement pouvait changer à tout moment. L'objectif était initialement de stabiliser ces commandes après quelques nouvelles versions, mais cela n'a pas été le cas jusqu'à présent.

Cela a entraîné plusieurs discussions sur la liste de diffusion Git, où les utilisateurs se demandaient s'ils pouvaient commencer à utiliser ces nouvelles commandes, ou si celles-ci pourraient éventuellement disparaître à nouveau. Mais étant donné qu'aucun changement significatif n'a été proposé, et que certains utilisateurs utilisent déjà ces commandes, nous avons décidé de les retirer de leur phase expérimentale dans la version Git 2.51.

Ce projet a été mené par Justin Tobler.

Prise en charge de la pagination pour git for-each-ref(1)

La commande git for-each-ref est utilisée pour indiquer toutes les références présentes dans un dépôt. Comme elle fait partie de la couche de plomberie de Git, cette commande est fréquemment utilisée par les forges logicielles d'hébergement pour lister sur leur interface utilisateur les références qui existent dans le dépôt. Mais à mesure que les dépôts grandissent, il n'est pas réaliste de lister toutes les références à la fois, car les plus grands dépôts peuvent en contenir des millions ! À la place, les forges ont tendance à paginer les références.

Une lacune importante émerge ainsi : git-for-each-ref ne sait pas ignorer les références des pages précédentes qui ont déjà été affichées. Par conséquent, cette commande peut devoir lister un grand nombre de références sans intérêt avant de commencer à indiquer les références requises pour la page actuelle. Ce processus est peu efficace et conduit à une latence plus élevée que nécessaire ou même à des délais d'attente dépassés.

Git 2.51.0 prend en charge une nouvelle option --start-after pour git for-each-ref, qui permet de paginer les données de sortie. Il est aussi possible de la combiner avec l'option --count pour itérer sur un lot de références.

$ git for-each-ref --count=10
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-001
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-002
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-003
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-004
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-005
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-006
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-007
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-008
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-009
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-010

$ git for-each-ref --count=10 --start-after=refs/heads/branch-010
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-011
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-012
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-013
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-014
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-015
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-016
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-017
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-018
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-019
9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-020

Ce projet a été mené par Karthik Nayak.

Perspectives

Prêt à découvrir ces améliorations ? Mettez à jour votre version Git et commencez à utiliser git switch et git restore dans vos workflows quotidiens.

Pour les utilisateurs de GitLab, ces améliorations de performances enrichiront automatiquement l'expérience de développement une fois la version de Git mise à jour.

Pour en savoir plus, consultez les notes de version officielles de Git 2.51.0 et explorez notre archive complète de le développement de Git.

Votre avis nous intéresse

Cet article de blog vous a plu ou vous avez des questions ou des commentaires ? Partagez vos réflexions en créant un sujet dans le forum de la communauté GitLab.
Share your feedback

Plus de 50 % des entreprises du classement Fortune 100 font confiance à GitLab

Commencez à livrer des logiciels de meilleurs qualité plus rapidement

Découvrez comment la plateforme DevSecOps intelligente

peut aider votre équipe.