Je pense que l'algo diff utilisé pour les fichiers pack était lié à l'un des encodages delta disponibles: initialement (2005) xdelta, puis libXDiff.
Cependant, comme détaillé ci-dessous, il est passé à une implémentation personnalisée.
Quoi qu'il en soit, comme mentionné ici:
Git effectue la deltification seulement dans les fichiers pack.
Mais lorsque vous poussez via SSH, git génère un fichier pack avec des commits que l'autre côté n'a pas, et ces packs sont des thin packs, donc ils ont aussi des deltas... mais le côté distant ajoute ensuite des bases à ces thin packs les rendant autonomes.
(note : créer de nombreux fichiers pack, ou récupérer des informations dans un énorme fichier pack est coûteux, et explique pourquoi git ne gère pas bien les fichiers volumineux ou les gros dépôts.
Voir plus sur "git avec de gros fichiers")
Ce fil de discussion nous rappelle également :
En fait, les fichiers pack et la deltification (LibXDiff, pas xdelta) étaient, d'après ce dont je me souviens et que je comprends, initialement à cause de la bande passante réseau (qui est bien plus coûteuse que l'espace disque), et de la performance E/S d'utilisation d'un seul fichier mmappé au lieu d'un très grand nombre d'objets lâches.
LibXDiff est mentionné dans ce fil de discussion de 2008.
Cependant, depuis lors, l'algo a évolué, probablement vers une version personnalisée, comme le montre ce fil de discussion de 2011, et comme l'en-tête de diff-delta.c
le souligne :
Donc, en termes stricts, le code actuel de Git ne ressemble en rien au code libxdiff.
Cependant, l'algorithme de base derrière les deux implémentations est le même.
Étudier la version libxdiff est probablement plus simple pour comprendre comment cela fonctionne.
/*
* diff-delta.c: génère un delta entre deux tampons
*
* Ce code a été grandement inspiré par certaines parties de LibXDiff de Davide Libenzi
* http://www.xmailserver.org/xdiff-lib.html
*
* Réécrit pour GIT par Nicolas Pitre , (C) 2005-2007
*/
Plus sur les fichiers pack dans le livre Git:
Git 2.18 ajoute à la description delta dans cette nouvelle section de documentation, qui indique maintenant (T2 2018) :
Types d'objets
Les types d'objets valides sont :
OBJ_COMMIT
(1)
OBJ_TREE
(2)
OBJ_BLOB
(3)
OBJ_TAG
(4)
OBJ_OFS_DELTA
(6)
OBJ_REF_DELTA
(7)
Le type 5 est réservé pour une expansion future. Le type 0 est invalide.
Représentation delta
Conceptuellement, il n'y a que quatre types d'objets : commit, arbre, tag et blob.
Cependant, pour économiser de l'espace, un objet peut être stocké sous forme de "delta" d'un autre objet "de base".
Ces représentations se voient attribuer de nouveaux types ofs-delta et ref-delta, qui sont valides uniquement dans un fichier pack.
À la fois ofs-delta
et ref-delta
stockent le "delta" à appliquer à un autre objet (appelé 'objet de base') pour reconstruire l'objet.
La différence entre eux est,
- ref-delta encode directement le nom de 20 bytes de l'objet de base.
- Si l'objet de base est dans le même pack, ofs-delta encode l'offset de l'objet de base dans le pack à la place.
L'objet de base pourrait également être deltifié s'il est dans le même pack.
Ref-delta peut également se référer à un objet hors du pack (c'est-à-dire le "thin pack" en question). Cependant, lorsqu'il est stocké sur disque, le pack doit être autonome pour éviter une dépendance cyclique.
Les données delta sont une séquence d'instructions pour reconstruire un objet à partir de l'objet de base.
Si l'objet de base est deltifié, il doit d'abord être converti en forme canonique. Chaque instruction ajoute de plus en plus de données à l'objet cible jusqu'à ce qu'il soit complet.
Jusqu'à présent, deux instructions sont prises en charge :
- une pour copier une plage d'octets à partir de l'objet source et
- une pour insérer de nouvelles données intégrées à l'instruction elle-même.
Chaque instruction a une longueur variable. Le type d'instruction est déterminé par le septième bit du premier octet. Les schémas suivants suivent la convention de la RFC 1951 (format de données compressées Deflate).