Que fait réellement git quand il dit qu'il «résout les deltas»?


187

Lors du premier clone d'un référentiel, git reçoit d'abord les objets (ce qui est assez évident), puis passe à peu près le même temps à "résoudre les deltas". Que se passe-t-il réellement pendant cette phase du clone?



1
Voir aussi, pour Git 2.20 (Q4 2018) et d'autres îles delta: stackoverflow.com/a/52458712/6309
VonC

Réponses:


54

Git utilise le codage delta pour stocker certains des objets dans des fichiers pack. Cependant, vous ne voulez pas avoir à lire chaque changement unique jamais sur un fichier donné afin d'obtenir la version actuelle, alors Git a aussi des instantanés occasionnels du contenu des fichiers stockés ainsi. «Résoudre les deltas» est l'étape qui consiste à s'assurer que tout cela reste cohérent.

Voici un chapitre de la section "Git Internals" du livre Pro Git, disponible en ligne, qui en parle.


80
Cette réponse est incorrecte. Il semble décrire comment fonctionne Mercurial, pas Git. Il apparaît dans les recherches Google pour ce problème, je ressens donc le besoin de répondre. Git ne stocke pas les différences entre les commits sous forme de deltas; Git est un magasin "d'objets entiers". En tant que tel, Git n'a pas besoin de "snapshots" pour afficher un fichier donné car l'historique des fichiers n'a pas besoin d'être reconstruit à partir des deltas. C'est ainsi que fonctionne Mercurial.
nexus dit le

12
Le seul endroit où l'encodage delta entre en jeu est dans le fichier pack qui est strictement destiné à la compression et au transfert - cela ne modifie pas la façon dont Git "voit" le monde. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/… ) Veuillez voir la réponse d'araqnid ci-dessous pour une réponse précise.
nexus dit le

4
Tout «instantané» signifie dans ce contexte est une copie complète d'un état de fichier, plutôt qu'une version codée en delta. Comme vous l' avez mentionné, Git fait usage delta-encodage dans packfiles. Personne n'a dit que cela "modifiait la façon dont Git voit le monde"; veuillez arrêter de projeter vos propres hypothèses.
Ambre

2
Votre réponse est toujours inexacte. "Git a également des instantanés occasionnels du contenu du fichier stocké." -- ce n'est pas correct. "La résolution des deltas est l'étape qui consiste à s'assurer que tout cela reste cohérent." - ce n'est pas non plus correct, la réponse d'araqnid ci-dessous est correcte.
nexus dit le

1
Comme décrit dans le chapitre mentionné ci-dessus, Git stocke toujours le contenu complet du fichier de la dernière version. Les versions précédentes sont stockées sous forme de fichiers codés en delta quand il s'agit de fichiers «libres». Périodiquement (soit en appelant, git gcsoit chaque fois que Git le juge nécessaire), Git compressera tous les fichiers "libres" dans un fichier pack pour économiser de l'espace et un fichier d'index dans ce fichier pack sera créé. Ainsi, zlib se compressera avec son propre algorithme delta mais Git utilise l'encodage delta pour stocker les versions précédentes. Étant donné que l'accès le plus courant et le plus fréquent est la dernière version, elle est stockée sous forme d'instantané.
BrionS

118

Les étapes de git clonesont:

  1. Recevoir un fichier "pack" de tous les objets de la base de données du référentiel
  2. Créer un fichier d'index pour le pack reçu
  3. Vérifiez la révision principale (pour un repo non nu, évidemment)

"Resolving deltas" est le message affiché pour la deuxième étape, indexant le fichier pack ("git index-pack").

Les fichiers de pack ne contiennent pas les ID d'objet réels, mais uniquement le contenu de l'objet. Donc, pour déterminer quels sont les ID d'objet, git doit faire une décompression + SHA1 de chaque objet du pack pour produire l'ID d'objet, qui est ensuite écrit dans le fichier d'index.

Un objet dans un fichier pack peut être stocké en tant que delta, c'est-à-dire une séquence de modifications à apporter à un autre objet. Dans ce cas, git doit récupérer l'objet de base, appliquer les commandes et SHA1 le résultat. L'objet de base lui-même peut devoir être dérivé en appliquant une séquence de commandes delta. (Même si dans le cas d'un clone, l'objet de base aura déjà été rencontré, il y a une limite au nombre d'objets fabriqués mis en cache en mémoire).

En résumé, l'étape de «résolution des deltas» implique la décompression et la somme de contrôle de l'ensemble de la base de données de repo, ce qui, sans surprise, prend un temps assez long. La décompression et le calcul des SHA1 prennent vraisemblablement plus de temps que l'application des commandes delta.

Dans le cas d'une extraction ultérieure, le fichier pack reçu peut contenir des références (en tant que bases d'objets delta) à d'autres objets que le git récepteur est censé avoir déjà. Dans ce cas, le git récepteur réécrit en fait le fichier de pack reçu pour inclure de tels objets référencés, de sorte que tout fichier de pack stocké soit autonome. C'est peut-être là que provient le message «résolution des deltas».


7
Cela peut-il être parallélisé?
brooksbp

Cette compression delta est-elle plus que le stockage de plusieurs objets dans un seul flux de données zlib?
fuz

1
@FUZxxl oui, il utilise un algorithme comme diff ou xdelta pour comparer deux blobs et produire un script d'édition
araqnid

@brooksbp: Uniquement avec des limitations. Parce que l'objet avec l'id 103fa49 peut avoir besoin de df85b51 pour être décodé, mais lorsque vous recevez 103fa49, df85b51 n'est pas encore là (les fichiers de pack sont strictement classés par hachages sha1). Donc, pour tout ce qui ne fait référence qu'à ce qui est déjà là, les choses sont faciles, mais pour tout le reste, vous devrez attendre qu'il soit reçu. Et cette compression delta peut être imbriquée, donc 103fa49 peut avoir besoin de 4e9ba42 qui à son tour besoin de 29ad945 qui à son tour a besoin de c9e645a ... vous obtenez l'image. [oui, j'ai remarqué que ça fait> 4 ans;)]
Bodo Thiesen

2
@brooksbp: Il s'avère que je me suis trompé, le fichier du pack n'a PAS besoin d'être trié par hachages sha1. De plus, lors de l'écriture, git écrit les objets nécessaires avant que les objets en aient besoin. Donc, en fait, vous devriez être en mesure de le paralléliser. Seul inconvénient qui reste: comme vous ne savez pas de quels objets vous aurez besoin plus tard, vous devrez en recréer encore et encore. Voir ici: kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen

4

Amber semble décrire le modèle d'objet utilisé par Mercurial ou similaire. Git ne stocke pas les deltas entre les versions suivantes d'un objet, mais plutôt des instantanés complets de l'objet, à chaque fois. Il compresse ensuite ces instantanés à l'aide de la compression delta, en essayant de trouver les bons deltas à utiliser, quel que soit leur emplacement dans l'historique.


5
En fait, bien que Git puisse stocker des objets en vrac, ils ne sont pas nécessairement toujours stockés en tant que tels - car les objets en vrac peuvent être supprimés et remplacés par du contenu compressé. Je ne pense pas que la réponse d'Amber ait dit quoi que ce soit sur les versions ultérieures.
AlBlue
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.