avec texte explicatif

This commit is contained in:
eleonore12345 2024-07-10 10:14:58 +02:00
parent 3fb2a481ca
commit 49f8746caf

102
texte_explicatif.txt Normal file
View File

@ -0,0 +1,102 @@
Comment minimiser la consommation en ressources mémoire et flux de données d'un clonage Git ?
# Contexte
Jean-Cloud est une petite association d'hébergement associatif sur du matériel de récupération. Elle lance en ce moment le projet Shlagernetes : un logiciel qui permet de répartir et gérer des services sur plusieurs serveurs de récupération. Git est utilisé dans certains cas pour installer un service sur un serveur ou le mettre à jour.
# Objectif
L'objectif est de trouver une combinaison de commandes Git. Cette combinaison doit permettre de cloner ou mettre à jour un dépôt Git et consommer le moins de ressources possibles. Par ressources, on entend le flux de données qui part du remote pour arriver au dossier local, ainsi que la place mémoire occupée par le dépôt sur le serveur local.
Le dépôt Git créé n'enverra aucune donnée au remote. Il n'aura aucune utilité de l'historique.
Il pourra éventuellement conserver certains fichiers locaux en plus de ses clonages Git. Il incluera les éventuels submodules. Il peut vouloir télécharger un commit d'une certaine branche ou tag.
# Procédé
Des tests sur différentes commandes ont été réalisés sur un dépôt factice. Le dossier de tests est transportable et peut être téléchargé ici. Attention, pour fonctionner en local, il nécessite d'autoriser le protocole pour les fichiers locaux : git config --global protocol.file.allow always.
Ce n'est pas la configuration par défaut car elle peut représenter une faille de sécurité.
Les tests consistent à analyser l'espace mémoire pris par le dépôt en local grâce à la commande bash "du", ainsi qu'à analyser le texte produit par Git lors du clonage.
# Résultats finaux
La combinaison finale retenue est :
## Pour cloner :
git clone --depth=1 --recurse-submodules --remote-submodules --shallow-submodules
depth=1 permet d'uniquement cloner le dernier commit et les objets nécessaires. Par défaut, elle est single-branch, mais il est possible de préciser --no-single-branch.
recurse-submodules s'assure que le contenu des submodules est cloné
remote-submodules s'assure que le contenu des submodules est cloné à partir du remote submodule originel
shallow-submodules s'assure que seul le dernier commit des submodules est importé (pour que cela fonctionne en local, il faut préciser ://file/ avant le chemin des submodules)
## Pour mettre à jour :
git submodule update --init --recursive --force --depth=1 --remote
git fetch --progress --tags --depth=1 --prune --prune-tags origin
git reset --hard origin/main
git reflog expire --expire=now --all
git gc --aggressive --prune=now
git submodule update --init --recursive --force --depth=1 --remote
init met à jour le fichier .gitmodules
recursive applique la commande aux submodules de submodules etc.
force permet d'ignorer les changements locaux aux submodules et d'automatiquement check out la nouvelle version
depth=1 permet de considérer uniquement le dernier commit du submodule
remote permet de mettre à jour depuis le remote submodule originel
git fetch --tags --depth=1 --prune --prune-tags origin
tags permet de fetch les tags, elle doit être précisée y compris si un tag est fetched par référence
depth=1 permet de considérer uniquement le dernier commit
prune permet de supprimer du dossier remote en local les références qui ne sont plus accessibles
prune-tags permet non seulement de supprimer du dossier remote en local les références qui ne sont plus accessibles, mais aussi de supprimer les les tags locaux qui n'existent pas sur le remote
git reset --hard origin/main
git reflog expire --expire=now --all
cette ligne permet de marquer tous les reflogs isolés comme expirés immédiatement au lieu de 90 jours plus tard. Cela permet un plus grand nettoyage par git gc. git rev-list permet de vérifier quels objets sont reliés et ne seront pas marqués comme expirés.
git gc --aggressive --prune=now
cette commande supprime les références non reliées et réorganise le dépôt pour l'optimiser.
aggressive invoque repack et prend plus de temps. repack défait et refait les packs, qui sont des unités de compression.
# Détails
Voici un résumé de différentes pistes explorées afin de réduire l'empreinte du dépôt Git.
## Clone partiel (partial) vs superficiel (shallow)
Un clone superficiel consiste à ne pas cloner tout l'historique du dépôt.
Un clone partiel consiste à ne pas cloner tous les fichiers et/ou dossiers du dépôt, selon un filtre. Les filtres peuvent concerner les Binary Large Objects (blobs) ou bien les trees. Si le filtre concerne l'ancienneté, un clone partiel peut alors aussi être un clone superficiel. Les clones partiels peuvent être créés grâce à la commande git clone --filter.
Lors de check-out ou switch, des objets initialement ignorés par le clone --filter peuvent être importés.
Dans notre cas, nous ne souhaitons garder que le tout dernier commit, qui sera dans tous les cas laissé passer par git clone --filter et ce n'est donc pas pertinent.
Les clones partiels peuvent aussi être créés par le sparse-checking. Certains fichiers et/ou dossiers n'apparaissent alors pas du tout dans le dossier local et ne sont pas concernés par les opérations git porcelain (de surface). Néanmoins, les objets associés à ces fichiers et dossiers sont toujours stockés dans le .git
Un clone superficiel peut être grâce à l'option depth=<nombre> qui indique le nombre de commits à conserver. Cette option est disponible pour la commande clone mais aussi fetch.
## Le large file storage
LFS est une extension Git qui permet de manipuler les fichiers choisis (par nom, expression ou taille) à l'aide d'un cache local. En effet, les fichiers sont remplacés par des références dans le dépôt GIt et un dossier local hors du dépôt est créé pour stocker les fichiers. Ils y sont téléchargés de manière lazy, c'est-à-dire uniquement lorsqu'ils sont checked out. Toutes les anciennes versions sont stockées sur un serveur en ligne.
C'est un mécanisme très intéressant, que nous ne retenons pas pour la même raison que le clone --filter : nous ne souhaitons garder que la toute dernière version des fichiers, qui serait dans tous les cas téléchargée par LFS.
## Suppression de l'historique
L'usage de la commande git filter-branch est déconseillé par la documentation Git. Elle présente plusieurs failles de sécurité et de performance. Elle permet de réécrire l'historique des branches grâce à des filtres.