Le projet Git a récemment publié la version 2.47.0 de Git. Jetons un coup d'œil aux points forts de cette nouvelle version, comprenant des contributions de l'équipe Git de GitLab et de la communauté Git au sens large.
Nouvelles options de configuration globales
Si vous suivez les dernières versions de Git, vous avez sûrement entendu parler du nouveau backend « reftable » introduit dans la version 2.45.0 de Git.
Auparavant, pour initialiser un dépôt au format « reftable », il fallait transmettre l'option --ref-format
à git-init(1) :
$ git init --ref-format reftable
Avec la nouvelle version 2.47, Git dispose désormais de l'option de configuration init.defaultRefFormat
,
laquelle indique à Git quel backend de gestion des références utiliser lors de l'initialisation d'un
dépôt. Cette dernière peut être utilisée pour remplacer le backend « fichiers » par défaut et commencer à utiliser le backend « reftable ». Pour la configuration, procédez comme suit :
$ git config set --global init.defaultRefFormat reftable
Comme certains d'entre vous le savent peut-être déjà, le format de hachage d'objets utilisé par les dépôts Git est
également configurable. Par défaut, les dépôts sont initialisés pour utiliser le
format d'objet SHA-1. Il existe toutefois une alternative, le format SHA-256, qui offre davantage de sécurité et qui est plus évolutif. Pour en savoir plus, consultez notre
article dédié à la prise en charge de SHA-256 dans Gitaly. Pour créer un dépôt SHA-256, vous devez transmettre l'option --object-format
à git-init(1) :
$ git init --object-format sha256
Cette nouvelle version de Git inclut une autre option de configuration : init.defaultObjectFormat
qui indique à Git le format d'objet à utiliser par défaut lors de l'initialisation d'un dépôt. Pour la configuration, procédez comme suit :
$ git config set --global init.defaultObjectFormat sha256
Il convient de noter que les dépôts SHA-256 ne sont pas interopérables avec les dépôts SHA-1 et que toutes les forges logicielles ne prennent pas en charge l'hébergement de dépôts SHA-256. GitLab a récemment annoncé une prise en charge expérimentale pour les dépôts SHA-256 pour celles et ceux qui souhaitent l'essayer.
Ces options fournissent un mécanisme utile pour commencer à utiliser ces fonctionnalités de dépôt plus simplement lors de l'initialisation d'un nouveau dépôt.
Ce projet a été mené par Patrick Steinhardt.
Nouvelle sous-commande pour git-refs(1)
La précédente version de Git avait introduit la commande git-refs(1) afin d'offrir un accès plus direct aux références d'un dépôt et fournissait la sous-commande « migrate » pour basculer d'un backend de gestion des références à un autre. Cette nouvelle version 2.47.0 introduit une nouvelle sous-commande « verify », qui permet à l'utilisateur de vérifier la cohérence de la base de données qui gère les références. Pour procéder à cette vérification dans un dépôt, il est courant d'utiliser la commande git-fsck(1).
Cette commande ne vérifie cependant pas explicitement la base de données qui gère les références du dépôt. Avec l'introduction du format de référence « reftable », lequel est un format binaire et donc plus difficile à inspecter manuellement, il est désormais encore plus important de mettre en place des outils pour combler cette lacune. Démontrons ce fait en configurant un dépôt avec une référence invalide :
# The "files" backend is used so we can easily create an invalid reference.
$ git init --ref-format files
$ git commit --allow-empty -m "init"
# A lone '@' is not a valid reference name.
$ cp .git/refs/heads/main .git/refs/heads/@
$ git refs verify
error: refs/heads/@: badRefName: invalid refname format
Nous constatons effectivement que la référence invalide a été détectée et qu'un message d'erreur a été envoyé à l'utilisateur. Bien que cet outil ne soit probablement pas destiné à être utilisé par l'utilisateur final, il est particulièrement utile côté serveur pour garantir la cohérence des dépôts. À terme, l'objectif est d'intégrer cette commande à git-fsck(1) afin de fournir un moyen unifié d'exécuter les contrôles de cohérence des dépôts.
Ce projet a été mené par Jialuo She dans le cadre du programme Google Summer of Code. Pour en savoir plus, consultez le rapport du GSoC de Jialuo She.
Améliorations relatives aux reftables
Cette nouvelle version inclut également des corrections pour certains bogues détectés dans le backend « reftable ». L'un d'entre eux est particulièrement intéressant et concerne la manière dont le compactage des tables était effectué.
Comme vous vous en souvenez peut-être, le backend « reftable » consiste en une série de tables contenant l'état de toutes les références dans le dépôt. Chaque opération atomique de modifications de références entraîne l'écriture d'une nouvelle table, laquelle est alors enregistrée dans le fichier « tables.list ». Pour réduire le nombre de tables présentes, les tables sont compactées pour suivre une séquence géométrique en fonction de la taille du fichier après chaque mise à jour des références. Une fois les tables compactées, le fichier « tables.list » est mis à jour pour refléter le nouvel état des reftables sur le disque.
Par conception, l'écriture et le compactage simultanés des tables sont autorisés. La synchronisation à certains moments est contrôlée par l'utilisation de fichiers de verrouillage. Par exemple, lorsque le compactage commence, le fichier « tables.list » est d'abord verrouillé afin qu'il puisse être lu de manière cohérente, et les tables nécessitant un compactage peuvent également être verrouillées. Comme le compactage des tables peut prendre un certain temps, le verrouillage est levé et les écritures simultanées peuvent alors commencer. Cette méthode est sûre, car les processus d’écriture simultanés savent qu'ils ne doivent pas modifier les tables verrouillées sur le point d'être compactées. Une fois que les nouvelles tables compactées ont été écrites, le fichier « tables.list » est à nouveau verrouillé et est, cette fois-ci, mis à jour pour refléter le nouvel état des tables.
Un problème subsiste cependant : que se passe-t-il si une mise à jour de référence simultanée écrit une nouvelle table dans le fichier « tables.list » à mi-chemin du compactage des tables après que le verrouillage initial a été levé, mais avant que le nouveau fichier « tables.list » n'ait été écrit ? Dans ce cas, le processus de compactage ignore alors l'existence de la nouvelle table et réécrit donc le fichier « tables.list » sans inclure la nouvelle table. Cette situation a pour effet d'ignorer la mise à jour de l'écriture simultanée et d'empêcher l’ajout, la mise à jour ou la suppression des références.
Heureusement, la solution pour remédier à ce problème est assez simple. Lorsque le processus de compactage obtient le verrou pour écrire dans le fichier « tables.list », il doit d'abord vérifier si des mises à jour du fichier ont eu lieu et recharger le fichier. Cela permet de s'assurer que les mises à jour simultanées des tables sont également reflétées correctement. Pour plus d'informations sur cette correction, consultez ce fil de discussion.
Ce projet a été mené par Patrick Steinhardt.
Corrections pour git-maintenance(1)
Au fur et à mesure qu'un dépôt évolue, il est important qu'il soit correctement maintenu. Par
défaut, Git exécute
git-maintenance(1) après certaines
opérations pour maintenir le dépôt fonctionnel. Afin d'éviter une maintenance
inutile, l'option --auto
est spécifiée et utilise une heuristique définie pour déterminer si les tâches de maintenance doivent être exécutées. Bien que la commande puisse être
configurée pour effectuer différentes tâches de maintenance, elle exécute simplement par défaut git-gc(1) en arrière-plan, permettant ainsi à l'utilisateur de poursuivre ses activités.
Tout fonctionne comme prévu jusqu'à ce que la maintenance soit configurée pour effectuer des tâches supplémentaires, différentes de celles prévues par défaut. Dans ce cas, les tâches de maintenance configurées s'exécutent au premier plan et le processus de maintenance initial ne s'interrompt pas tant que toutes les tâches ne sont pas terminées. Seule la tâche « gc » s'exécute en arrière-plan comme prévu. En effet, git-gc(1) se détache malencontreusement lorsqu'elle est exécutée avec --auto
, tandis que les autres tâches de maintenance n'ont aucun mécanisme pour le faire. Résultat ? Un ralentissement de certaines commandes Git, la maintenance automatique devant s'exécuter entièrement avant qu'elles ne puissent se terminer.
Cette nouvelle version résout ce problème en ajoutant à git-maintenance(1) l'option --detach
, qui permet à l'ensemble du processus git-maintenance(1) de s'exécuter en arrière-plan à la place des tâches individuelles. La maintenance automatique effectuée par Git a également été mise à jour pour utiliser cette nouvelle option. Pour plus d'informations sur cette correction, consultez ce fil de discussion pour en savoir plus.
Il a été mentionné précédemment que l'auto-maintenance utilise un ensemble
d'heuristiques pour déterminer si certaines opérations de maintenance doivent être effectuées ou non. Malheureusement, pour le backend « fichiers » de gestion des références, lorsque
git-pack-refs(1) s'exécute avec
l'option --auto
, il n'y a pas de telle heuristique, et toutes les références non compactées sont inconditionnellement compactées dans un fichier « packed-refs ». Pour les dépôts avec de nombreuses références, la réécriture du fichier « packed-refs » peut prendre beaucoup de temps.
Cette nouvelle version introduit également une heuristique qui décide s'il faut compacter les références non compactées dans le backend « fichiers ». Cette heuristique prend en compte la taille du fichier « packed-refs » existant et le nombre de références non compactées présentes dans le dépôt. Plus le fichier « packed-refs » est volumineux, plus le seuil du nombre de références non compactées est élevé avant que le compactage des références ne se produise. Cela permet de rendre moins agressif le compactage des références dans le backend « fichiers » tout en maintenant le dépôt dans un état correct. Consultez ce fil de discussion pour plus d'informations.
Ce projet a été mené par Patrick Steinhardt.
Réusinage du code et amélioration de la maintenabilité
En plus des changements fonctionnels, un travail de réusinage et de nettoyage du code est également en cours. Très précieuses, ces améliorations aident le projet à se rapprocher de son objectif de longue date qui est de créer une bibliothèque de librairies de ses composants internes. Pour en savoir plus, consultez cette récente mise à jour du fil de discussion sur la création d'une bibliothèque de librairies.
L'un des domaines d'amélioration concerne la résolution des fuites de mémoire. Le projet Git présente en effet un certain nombre de fuites de mémoire. Ces fuites ne posent généralement pas de problème puisqu'un processus Git ne s'exécute que pendant une courte période et qu'un nettoyage est effectué par le système par la suite. Dans un contexte de création d'une bibliothèque de librairies, il s'agit cependant d'un problème qu'il convient de résoudre. Les tests du projet peuvent être compilés à l'aide d'un outil conçu pour détecter les fuites. Cependant, en raison de la présence de fuites existantes, il est difficile de valider et de garantir que les nouveaux changements n'introduisent pas d'autres fuites. Des efforts continus ont été déployés pour corriger toutes les fuites de mémoire détectées par les tests existants dans le projet. Les tests qui n'ont détecté aucune fuite sont ensuite mis en évidence avec la mention TEST_PASSES_SANITIZE_LEAK=true
afin d'indiquer qu'ils sont supposés être exempts de fuites à l'avenir. Le projet compte aujourd'hui 60 fichiers de test contenant des fuites de mémoire, contre 223 auparavant.
Une autre initiative en cours a pour but de réduire l'utilisation de variables globales
dans l'ensemble du projet. L'une de ces fameuses variables globales est the_repository
, laquelle contient l'état du dépôt en cours d’utilisation et est référencée dans l'ensemble du projet. La nouvelle version Git 2.47.0 s'accompagne d'un certain nombre de correctifs qui suppriment l'utilisation de the_repository
en faveur d'une transmission directe de la valeur là où c'est nécessaire. Les sous-systèmes du projet Git qui dépendent encore de the_repository
définissent la variable USE_THE_REPOSITORY_VARIABLE
, permettant ainsi d'utiliser la variable globale. De cette manière, les sous-systèmes refs, config et path ne dépendent plus de son utilisation.
Ce projet a été mené par Patrick Steinhardt avec l'aide de John Cai et Jeff King.
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 et en consultant les ressources suivantes :