Blog Open source Nouveautés de Git 2.46.0
Date de la mise à jour : August 15, 2024
Lecture : 10 min

Nouveautés de Git 2.46.0

Découvrez les contributions de l'équipe Git de GitLab et de la communauté Git au sens large à la dernière version de Git.

git - cover

Le projet Git a récemment publié la version 2.46.0 de Git. Jetons un coup d'œil aux points forts de cette version, comprenant des contributions de l'équipe Git de GitLab et de la communauté Git au sens large.

Outils pour migrer les backends de références

Dans la version Git 2.45.0 précédente, le format « reftable » est devenu le nouveau backend pour le stockage des références. Ce nouveau format de référence vise à améliorer les performances et l'efficacité des dépôts Git, en particulier lorsque le nombre de références devient très élevé. Si le backend « reftable » ne vous est pas encore familier, n'hésitez pas à consultez notre précédent article de blog consacré à la version 2.45.0 de Git dans lequel nous présentons ce nouveau format, ainsi que notre guide du débutant pour en savoir plus sur le fonctionnement des reftables.

Le backend « reftable » offre un format de stockage sur disque différent de l'ancien format de backend basé sur les fichiers. Par conséquent, l’utilisation du format « reftable » avec un dépôt existant, nécessite une conversion entre les différents formats. Pour cela, une nouvelle commande git-refs(1) a été introduite, incluant la sous-commande migrate pour effectuer les migrations de backend de référence. Voici un exemple illustrant l'utilisation de cette commande :

# Initialize a new repository as “bare” so it does not contain reflogs.
$ git init --bare .
$ git commit --allow-empty -m "init"
# Populate repository with references in the files backend.
$ git branch foo
$ git branch bar
$ tree .git/refs
.git/refs
├── heads
│   ├── bar
│   ├── foo
│   ├── main
└── tags
# Perform reference migration to reftables format.
$ git refs migrate --ref-format=reftable
# Check that reftables backend is now in use.
$ tree .git/reftable
.git/reftable
├── 0x000000000001-0x000000000001-a3451eed.ref
└── tables.list
# Check the repository config to see the updated `refstorage` format.
$ cat config
[core]
        repositoryformatversion = 1
        filemode = true
        bare = true
        ignorecase = true
        precomposeunicode = true
[extensions]
        refstorage = reftable

Une fois qu'un dépôt est migré, le format de stockage sur disque est mis à jour, permettant ainsi l'utilisation du backend « reftable ». Les opérations Git dans le dépôt continuent de fonctionner normalement et d'interagir avec les dépôts distants comme elles le faisaient auparavant. La migration n'a d'incidence que sur la manière dont les références sont stockées en interne pour le dépôt. Si vous souhaitez revenir au backend « fichiers », vous pouvez le faire avec la même commande en spécifiant à la place --ref-format=files.

L'outil de migration présente actuellement certaines limitations notables. Les reflogs dans un dépôt font partie du backend de gestion des références et nécessitent également une migration lors du changement de format. Malheureusement, l'outil n'est pas encore capable de convertir les reflogs entre les backends « fichiers » et les backends « reftable ». De plus, un dépôt avec des arbres de travail dispose en réalité de plusieurs ref stores et l'outil de migration ne prend pas encore en charge ce scénario. Par conséquent, si un dépôt contient des reflogs ou des arbres de travail, la migration des références n'est actuellement pas possible. Ces limitations pourraient être résolues dans les futures versions.

Les dépôts Git « bare » ne contiennent pas de reflogs, ce qui facilite leur migration. Pour migrer un dépôt « non bare » standard, les reflogs doivent d'abord être supprimés. Ainsi, il est possible de migrer tout dépôt dépourvu de reflog et d'arbre de travail. En tenant compte de ces limitations, cet outil de migration peut être très utile pour profiter des avantages du backend « reftable » dans vos dépôts existants.

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

Mises à jour des références symboliques transactionnelles

La commande git-update-ref(1) permet de mettre à jour les références dans un dépôt Git. Ces mises à jour de références peuvent également être effectuées de manière atomique en bloc via des transactions, en utilisant la commande git update-ref --stdin pour transmettre les informations de mise à jour de références à stdin. Voici un exemple :

$ git init .
$ git branch -m main
$ git commit --allow-empty -m "foo" && git commit --allow-empty -m "bar"
# Retrieve the object ID of the two commits created.
$ git rev-parse main~ main
567aac2b3d1fbf0bd2433f669eb0b82a0348775e
3b13462a9a42e0a3130b9cbc472ab479d3ef0631
# Start transaction, provide update-ref instructions, and commit.
$ git update-ref --stdin <<EOF
> start
> create refs/heads/new-ref 3b13462a9a42e0a3130b9cbc472ab479d3ef0631
> update refs/heads/main 567aac2b3d1fbf0bd2433f669eb0b82a0348775e
> commit
> EOF
$ git for-each-ref
567aac2b3d1fbf0bd2433f669eb0b82a0348775e commit refs/heads/main
3b13462a9a42e0a3130b9cbc472ab479d3ef0631 commit refs/heads/my-ref

Dans cet exemple, une fois la transaction validée, une nouvelle branche est créée et pointe vers le commit « bar » tandis que la branche principale est mise à jour et pointe vers le commit « foo » précédent. La validation de la transaction exécute les mises à jour des références spécifiées de manière atomique. Si une mise à jour concernant une référence particulière échoue, la transaction est abandonnée et aucune mise à jour de références n'est effectuée.

Il convient de noter ici qu'aucune instruction quant à la prise en charge des mises à jour des références symboliques n'est disponible pour ces transactions. Si un utilisateur souhaite mettre à jour une référence symbolique en même temps que d'autres références de manière atomique dans une seule transaction, il n'existe pas d'outil pour le faire. Dans la nouvelle version de Git, les instructions symref-create, symref-update, symref-delete et symref-verify sont introduites pour fournir cette fonctionnalité.

# Create a symref that will be updated during the next operation.
$ git symbolic-ref refs/heads/symref refs/heads/main
# The --no-deref flag is required to ensure the symref itself is updated.
$ git update-ref --stdin --no-deref <<EOF
> start
> symref-create refs/heads/new-symref refs/heads/main
> symref-update refs/heads/symref refs/heads/new-ref
> commit
> EOF
$ git symbolic-ref refs/heads/symref
refs/heads/new-ref
$ git symbolic-ref refs/heads/new-symref
refs/heads/main

L'exemple ci-dessus illustre la création d'une nouvelle référence symbolique et la mise à jour d'une autre au cours d'une transaction. Ces nouvelles instructions pour les références symboliques peuvent désormais être combinées avec les instructions existantes afin de réaliser toutes sortes de mises à jour de références dans une seule transaction. Pour en savoir plus sur chacune de ces nouvelles instructions, consultez la documentation.

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

Améliorations de l'expérience utilisateur pour git-config(1)

La commande git-config(1) est utilisée dans Git pour visualiser et modifier les options de configuration, tant au niveau local (pour un dépôt spécifique) qu'au niveau global (pour l'ensemble de l'interface utilisateur). Les modes d'interaction avec la configuration peuvent être choisis explicitement à l'aide d'indicateurs spécifiques ou déterminés implicitement en fonction du nombre d'arguments fournis à la commande. Voici un exemple :

$ git config --list
# Explicit retrieval of username configuration
$ git config --get user.name
# Implicit retrieval of username configuration
$ git config user.name
# Explicit setting of username configuration
$ git config --set user.name "Sidney Jones"
# Implicit setting of username configuration
$ git config user.name "Sidney Jones"
# An optional third argument is also accepted. What do you think this does?
$ git config <name> [<value> [<value-pattern>]]

Globalement, l'interface utilisateur de git-config(1) n'est pas cohérente avec le fonctionnement d'autres commandes Git plus récentes, où l'on utilise généralement des sous-commandes. Par exemple, git remote list. Cette nouvelle version Git introduit les sous-commandes list, get, set, unset, rename-section, remove-section et edit pour la commande config, tout en conservant l'ancienne syntaxe. Ce changement vise à améliorer l'expérience utilisateur en adaptant la commande config pour qu'elle suive des pratiques plus modernes et soit davantage alignée avec les autres commandes de Git. Par exemple :

$ git config list
$ git config get user.name
$ git config set user.name "Sidney Jones"

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

Correction de la régression des performances

Les opérations Git qui utilisent des attributs reposent sur la lecture des fichiers .gitattributes présents dans l'arbre de travail du dépôt. Cela pose un problème pour les dépôts Git « bare » qui sont, par définition, dépourvus d'un arbre de travail. Pour contourner ce problème, Git dispose de la configuration attr.tree, qui permet de définir un arbre source et de l'utiliser pour en extraire des attributs.

Dans la version 2.43.0 de Git, Git a commencé à utiliser par défaut l'arborescence de HEAD comme source des attributs Git dans le cas de dépôts « bare  ». Malheureusement, cette charge de travail supplémentaire liée à la recherche de fichiers d'attributs Git a eu de graves impacts sur les performances. En effet, à chaque recherche d'attribut, l'arbre source est parcouru dans son ensemble pour rechercher un fichier .gitattributes associé, si attr.tree est défini. Plus l'arbre source du dépôt est grand et profond, plus la régression des performances est évidente. Par exemple, des tests de performance réalisés sur le dépôt linux.git ont montré que git-pack-objects(1) mettait 1,68 fois plus de temps à s'exécuter. Cela peut entraîner des ralentissements lors d'opérations de clonage ou de récupération.

# attr.tree set to HEAD as done by default in Git version 2.43.0.
Benchmark 1: git -c attr.tree=HEAD pack-objects --all --stdout </dev/null >/dev/null
  Time (mean ± σ):     133.807 s ±  4.866 s    [User: 129.034 s, System: 6.671 s]
  Range (min … max):   128.447 s … 137.945 s    3 runs

# attr.tree is set to an empty tree to disable attribute lookup as done in Git versions prior to 2.43.0.
Benchmark 2: git -c attr.tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 pack-objects --all --stdout </dev/null >/dev/null
  Time (mean ± σ):     79.442 s ±  0.822 s    [User: 77.500 s, System: 6.056 s]
  Range (min … max):   78.583 s … 80.221 s    3 runs

Les commandes Git les plus impactées étaient clone, pull, fetch et diff, particulièrement lorsqu'elles étaient utilisées sur des dépôts avec des arborescences volumineuses ou profondes. Par conséquent, dans Git 2.46.0, la configuration attr.tree a été partiellement modifiée pour ne plus être définie sur HEAD par défaut afin de remédier à la régression des performances. Pour en savoir plus, consultez ce fil de discussion.

Migration des tests unitaires

Historiquement, pour tester Git, les développeurs utilisaient des scripts shell pour réaliser des tests de bout en bout. Un framework de tests unitaires écrit en C a été récemment intégré au projet Git. Ce nouveau framework permet de tester en détail les implémentations à un niveau granulaire, tel que chaque appel de fonction, et complète les tests de bout en bout existants. Certains tests de bout en bout existants sont plus adaptés aux tests unitaires et sont donc de bons candidats pour le portage de tests.

Cette année, GitLab continu d'aider les contributeurs du Google Summer of Code (GSoC) qui travaillent sur le projet Git. Grâce aux efforts déployés dans le cadre de ces projets GSoC et à la contribution de la communauté Git au sens large, certains tests existants sont révisés et migrés vers le framework de tests unitaires. Pour la sortie de la nouvelle version Git 2.46.0, plusieurs contributions ont été apportées dans le but d'améliorer les tests dans le projet Git. Pour suivre l'avancement de ces projets de contributeurs GSoC, consultez les blogs de Chandra et Ghanshyam.

Correction du bundle URI

En général, lorsqu'un client récupère des données à partir d'un dépôt distant, tous les objets nécessaires sont envoyés dans un fichier groupé généré par le serveur distant. Pour éviter une partie de ce traitement, les serveurs peuvent choisir de proposer des bundles prêts à l'emploi, stockés séparément du serveur distant, qui contiennent des ensembles de références et d'objets dont le client peut avoir besoin. Le client peut d'abord récupérer ces bundles grâce à un mécanisme appelé bundle-uri.

Grâce à Xing Xin, un problème a été identifié et corrigé : Git, malgré le téléchargement de certains bundles, continuait de télécharger tous les objets et les références depuis le dépôt distant, comme si aucun bundle n'avait été récupéré. La raison de ce problème était que Git ne découvrait pas correctement l'ensemble des bundles téléchargés, ce qui entraînait la nécessité de récupérer les bundles suivants depuis le dépôt distant. Grâce à cette correction, les dépôts distants utilisant le mécanisme bundle-uri peuvent éviter d'avoir à effectuer un travail redondant et ainsi améliorer les performances.

En savoir plus

Cet article n'a mis en évidence que quelques-unes des contributions apportées par GitLab et la communauté Git au sens large pour cette nouvelle version. Vous pouvez approfondir ce sujet en lisant l'annonce officielle du projet Git. Consultez également nos précédents articles de blog sur les nouvelles versions de Git pour en découvrir davantage sur les contributions de l'équipe GitLab.

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 nouveau sujet dans le forum de la communauté GitLab. Partager votre expérience

Prêt à vous lancer ?

Découvrez comment la plateforme DevSecOps de GitLab peut aider votre équipe.

Profiter d'un essai gratuit

Découvrez le forfait qui convient le mieux à votre équipe

En savoir plus sur la tarification

Découvrez ce que GitLab peut offrir à votre équipe

Échanger avec un expert