76 votes

Les fichiers de pack de Git sont-ils des deltas plutôt que des instantanés?

L'une des principales différences entre Git et la plupart des autres systèmes de contrôle de version, c'est que les autres ont tendance à stocker commet une série de deltas - révisions entre un commit et le suivant. Cela semble logique, puisque c'est la plus petite quantité possible d'informations à stocker sur un commit. Mais plus le commettre l'histoire se, plus de calcul qu'il faut pour comparer les gammes de révisions.

En revanche, Git stocke une image complète de l'ensemble du projet dans chaque révision. La raison pour laquelle ce n'est pas faire de l'opération de la taille de croître de façon spectaculaire avec chaque commit est chaque fichier du projet est stocké en tant que fichier dans le sous-répertoire Git, nommé pour le hachage de son contenu. Donc, si le contenu n'a pas changé, le hash n'a pas changé, et que la livraison juste des points pour le même fichier. Et il y a d'autres optimisations.

Tout cela fait sens pour moi jusqu'à ce que je suis tombé sur cette information sur le pack de fichiers, dans lequel Git met régulièrement des données pour économiser de l'espace:

Afin d'économiser de l'espace, Git utilise la packfile. C'est un format où Git enregistre uniquement les la partie qui a changé dans la deuxième fichier, avec un pointeur vers le fichier, il est similaire à.

N'est-ce pas, fondamentalement, de revenir à stocker les deltas? Si non, comment est-il différent? Comment est-ce à éviter de soumettre Git pour les mêmes problèmes que les autres versions de systèmes de contrôles?

Par exemple, Subversion utilise les deltas, et la restauration de 50 versions moyens de défaire 50 diffs, alors qu'avec Git, vous pouvez simplement saisir la appropriée de l'instantané. À moins que git stocke également 50 diff dans le packfiles... est-il un mécanisme qui dit "après quelques petit nombre de deltas, nous allons stocker un tout nouveau snapshot" afin de ne pas accumuler trop grandes d'une révision? Sinon, comment peut-Git éviter les inconvénients des deltas?

73voto

Chris Johnsen Points 50064

Résumé:
Git du pack fichiers sont soigneusement construits pour utiliser efficacement les caches et fournir "gentil" modèles d'accès pour les commandes courantes et pour la lecture récemment référencé objets.


Git du fichier de pack le format est assez souple (voir Documentation/technical/pack-format.txt, ou La Packfile dans Le Git Community Book). Les fichiers de pack de stocker des objets dans les deux principaux moyens: "undeltified" (prendre les premières données de l'objet et dégonfler-compresser c'), ou "deltified" (la forme d'un delta contre un autre objet, puis dégonflez-compresser le résultant delta de données). Les objets stockés dans un pack peut être dans n'importe quel ordre (ils ne sont pas (nécessairement) être triée par type d'objet, nom de l'objet, ou tout autre attribut) et deltified objets peuvent être faites à l'encontre de tout autre objet du même type.

Git est un pack d'objets de commande utilise plusieurs heuristiquespour fournir un excellent localité de référence pour les communes commandes. Ces heuristiques de contrôler à la fois la sélection de la base objets pour deltified objets et l'ordre des objets. Chaque mécanisme pour la plupart indépendants, mais ils partagent certains objectifs.

Git ne former de longues chaînes de delta objets compressés, mais l' heuristiques essayer de faire en sorte que seuls les "vieux" objets se trouvent aux extrémités de les longues chaînes. Le delta de la base de cache (qui est contrôlé par le core.deltaBaseCacheLimit variable de configuration) est automatiquement utilisé et peut réduire considérablement le nombre de "reconstruit" nécessaire pour les commandes qui ont besoin de lire un grand nombre d'objets (par exemple, git log -p).

Compression Delta Heuristique

Typique d'un dépôt Git stocke un très grand nombre d'objets, de sorte il ne peut pas raisonnablement comparer tous à trouver les paires (et les chaînes), ce qui rapportera le plus petit delta représentations.

Le delta de la base de sélection heuristique est basée sur l'idée que l' bonne delta bases sera trouvé entre les objets avec les mêmes noms de fichiers et de tailles. Chaque type d'objet est traitée séparément (c'est à dire un objet d'un type ne sera jamais utilisé comme la base de delta pour une objet d'un autre type).

Pour l'application du delta de la base de sélection, les objets sont triés (principalement) par nom de fichier et la taille. Une fenêtre dans cette liste triée est utilisé pour limiter l' le nombre d'objets qui sont considérés comme de possibles delta bases. Si une "bonne"1 delta de la représentation n'est pas trouvée pour un objet parmi les objets à sa fenêtre, alors l'objet ne sera pas delta compressé.

La taille de la fenêtre est contrôlée par l' --window= option de git pack-objects, ou l' pack.window variable de configuration. L' profondeur maximale d'une chaîne delta est contrôlée par l' --depth= option d' git pack-objects, ou l' pack.depthconfiguration variable. L' --aggressive option de git gc considérablement agrandit à la fois la taille de la fenêtre et de la profondeur maximale pour tenter de créer un petit pack de fichier.

Le nom de fichier de tri touffes ensemble les objets pour les entrées avec des noms identiques (ou au moins similaire fins (par exemple, .c)). La taille le tri est de la plus grande à la plus petite, de sorte que les deltas à la suppression des données sont préféré deltas qui ajoutent des données (depuis le retrait des deltas ont plus court les représentations) et de sorte que le plus tôt, d'objets de taille (généralement une version plus récente) ont tendance à être représenté avec la plaine de compression.

1 Ce qui constitue une "assez bonne" dépend de la taille de l'objet en question et de son potentiel de base de delta ainsi que la profondeur de ses delta de la chaîne.

Objet De La Commande Heuristique

Les objets sont stockés dans les fichiers du pack dans une "plus récemment référencé" ordre. Les objets nécessaires à la reconstruction de l'histoire la plus récente sont placé plus haut dans le pack, et ils seront rapprochés. Cette fonctionne généralement bien pour les OS de caches.

Tous les commettre les objets sont triés par commettre date (les plus récents en premier) et stockés ensemble. Ce placement et de commande optimise le disque les accès nécessaires à la marche de l'histoire graphique et de l'extrait de base de commettre de l'information (par exemple, git log).

L'arbre et les objets blob sont stockés en commençant par l'arbre de la tout d'abord stockées (la plus récente) s'engager. Chaque arbre est traité en profondeur première de la mode, de ranger tous les objets qui n'ont pas déjà été stockée. Cela met tous les arbres et les gouttes nécessaires pour reconstruire la plus récente s'engager ensemble dans un seul endroit. Les arbres et les objets blob n'ont pas encore été enregistrés, mais qui sont nécessaires pour des commits sont stocké à côté, dans le triées en ordre de validation.

L'objet final de la commande est légèrement affectée par le delta de la base de sélection si un objet est sélectionné pour le delta de la représentation et de son objet de base n'a pas été sauvegardé, puis son objet de base est stockée immédiatement avant la deltified objet lui-même. Cela empêche probablement le disque le cache en raison de la non-linéaire d'accès nécessaire à la lecture d'un objet de base qui auraient "naturellement" été stockées plus tard dans le fichier de pack.

8voto

Greg Hewgill Points 356191

L'utilisation de delta de stockage dans le fichier de pack est juste un détail d'implémentation. À ce niveau, Git ne sais pas pourquoi ou comment quelque chose a changé à partir d'une révision à l'autre, plutôt il sait juste que blob B est assez similaire à goutte Une exception pour ces changements de C. Donc il ne stocker blob et les changements C (si elle choisit de le faire -, elle pourrait aussi choisir de stocker blob blob et B).

Lors de la récupération d'objets à partir du fichier de pack, le delta de stockage n'est pas exposé à l'appelant. L'appelant voit encore complète des gouttes. Donc, Git fonctionne de la même manière qu'il a toujours sans le delta de stockage d'optimisation.

4voto

VonC Points 414372

Comme je l'ai mentionné dans "Ce sont git mince packs?"

Git ne deltification seulement dans packfiles

J'ai détaillé le delta encodage utilisé pour les fichiers du pack "Est le git diff binaire de l'algorithme (delta de stockage) normalisée?"

Notez que l' core.deltaBaseCacheLimit config qui contrôle la taille par défaut pour le fichier de pack sera bientôt tombé de 16 à 96 MO, pour Git 2.0.x/2.1 (T3 2014).

Voir commettre 4874f54 par David Kastrup (Mai 2014):

Bosse de base.deltaBaseCacheLimit à 96m

La valeur par défaut de 16m provoque une sévère raclée pour les grandes delta chaînes combiné avec de gros fichiers.

Voici quelques repères (pu variante de l' git blame):

time git blame -C src/xdisp.c >/dev/null

pour un dépôt d'Emacs remballé avec git gc --aggressive (v1.9, résultant en une taille de fenêtre de 250) situé sur un disque SSD.
Le fichier en question a propos de 30000 lignes, 1 mo de taille, et une histoire à propos de 2500 engage.

16m (previous default):
  real  3m33.936s
  user  2m15.396s
  sys   1m17.352s

96m:
  real  2m5.668s
  user  1m50.784s
  sys   0m14.288s

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X