2012-02-21 6 views
22

Lorsque j'exécute git gc ou git repack sur mon dépôt Git, il affiche une ligne «Total» une fois l'opération terminée. Que signifient ces chiffres?Que signifient les nombres dans la ligne "Total" de la sortie de repack git/git de git?

Quelques exemples d'un dépôt assez petit:

$ git gc 
... 
Total 576 (delta 315), reused 576 (delta 315) 

$ git repack -afd --depth=250 --window=250 
... 
Total 576 (delta 334), reused 242 (delta 0) 

Et l'un d'un dépôt beaucoup plus grand:

$ git gc 
... 
Total 347629 (delta 289610), reused 342219 (delta 285060) 
... 

Je peux deviner ce que le premier numéro de « Total » est: le nombre des objets Git (donc commits, arbres et fichiers) dans le dépôt. Que signifient réellement tous les autres?

J'ai déjà regardé les pages de manuel git-gc(1) et git-repack(1), et j'ai parcouru leurs «See also» aussi, et mes tentatives de Google n'ont produit que des résultats non pertinents.

+0

http://github.com/git/git/blob/master/builtin/pack-objects.c –

+0

@JoshLee J'ai (maintenant) regardé brièvement le code, et ne peut pas facilement travailler sur ce qui se passe. Merci pour le pointeur, cependant :) –

Répondre

22

J'ai fait un peu de travail avec dulwich, une implémentation python pure de Git. Ce que je suis sur le point de dire ici reflète mon expérience avec l'implémentation git de dulwich, pas la source git canonique et donc il peut y avoir des différences.

Git est remarquablement simple - je veux dire, tellement simple qu'il confond! Le nom est vraiment approprié à son design qui est très intelligent en raison de sa stupidité. Lorsque vous validez quelque chose, git prend ce qu'il y a dans l'index (zone de transfert) et crée des éléments de résumé SHA, ainsi chaque fichier reçoit SHAed et les fichiers de chaque répertoire sont SHA comme objets blob et bien sûr la structure de répertoire est SHAed objets d'arbre, et tout ce qui est lié à un objet commit qui a aussi un SHA. Git les envoie directement dans le système de fichiers .git/objects lorsqu'il traite le commit. S'il réussit à les virer tous, il écrit simplement le SHA de l'objet commit le plus récent dans .git/refs/heads /.

De temps en temps, un commit peut échouer à mi-parcours. Si quelque chose ne parvient pas à écrire dans .git/objets, git ne nettoie pas à ce moment. En effet, d'habitude, vous corrigez le problème et recommencez le commit - dans ce cas, git redémarrera exactement à partir de l'endroit où il s'était précédemment arrêté, c'est-à-dire à mi-chemin de la validation.

C'est ici qu'intervient git gc. Il analyse simplement tous les objets dans .git/objects, en marquant tous ceux qui sont référencés d'une façon ou d'une autre par un HEAD ou un BRANCH. Tout ce qui reste est évidemment orphelin et n'a rien à voir avec quelque chose d'important, donc il peut être supprimé. C'est pourquoi si vous branchez, travaillez un peu sur cette branche, mais que vous l'abandonnez par la suite et que vous supprimez toute référence à votre repit git, le git gc périodique qui s'exécute va purger totalement votre branche. Cela peut surprendre certains anciens utilisateurs de VCS, par ex. CVS n'a jamais rien oublié sauf quand il s'est écrasé ou s'est corrompu (ce qui était souvent le cas).

git repack (vraiment git-pack-objects) est totalement différent de git gc (comme dans, une commande séparée et une opération bien que git gc puisse appeler git repack). Comme je l'ai mentionné plus tôt, git allume tout dans son propre fichier SHAed. Il gzip les avant d'aller au stockage de disque, mais évidemment ce n'est pas l'espace efficace sur le long terme. Donc, ce que git-pack-objects fait est d'examiner une série d'objets SHA pour n'importe où où les données se répliquent à travers les révisions. Il ne se soucie pas quel type d'objet SHA c'est - tous sont considérés égaux pour l'emballage. Il génère ensuite des deltas binaires là où cela a du sens et stocke le lot entier sous la forme d'un fichier .pack dans .git/objects/pack, en supprimant les objets empaquetés de la structure de répertoires normale.

Notez que généralement les objets git-pack en créent un nouveau.empaquetez le fichier plutôt que de remplacer les fichiers .pack existants, si le fichier pack le plus récent a une taille inférieure à 1Mb. Ainsi, au fil du temps, plusieurs fichiers .pack apparaîtront dans .git/objects/pack. En effet, lorsque vous récupérez, vous demandez simplement au repo distant d'emballer tous les éléments non emballés et d'envoyer les fichiers .pack que le repo de récupération n'a pas dans le repo de récupération. git repack appelle simplement git-pack-objects mais lui dit de fusionner les fichiers .pack comme bon lui semble. Cela implique la décompression de tout ce qui a changé, la régénération des deltas binaires et la recompression. Donc, pour répondre à votre question, la ligne totale fait référence au nombre total d'objets dans le repo. Git. Le premier nombre delta est le nombre de ces objets totaux qui sont des objets delta binaires, c'est-à-dire le nombre d'objets que git a décidé ont une forte similarité avec d'autres objets et peuvent être stockés comme un delta binaire. Le nombre réutilisé indique combien d'objets provenant d'une source compressée (c'est-à-dire un fichier pack) sont utilisés sans avoir été recompressés pour inclure des changements plus récents. Cela se produit lorsque vous avez plusieurs fichiers packs mais où un objet SHA plus récent fait référence à un élément d'un ancien fichier pack comme base, puis lui applique des deltas pour le rendre moderne. Cela permet à git d'utiliser des révisions de données plus anciennes précédemment compressées sans avoir à le recompresser pour inclure des ajouts plus récents. Notez que git peut s'ajouter à un fichier pack existant sans réécrire le fichier pack entier. D'une manière générale, un compte fortement réutilisé indique qu'un peu d'espace peut être récupéré avec un repack complet (c'est-à-dire un repack git -a) qui sera toujours réutilisé à 0. Cependant, généralement git prendra silencieusement soin de tout cela pour vous. En outre, faire des recopies complètes peut forcer certaines extractions git à partir de zéro car les packs diffèrent - cela dépend des paramètres du serveur (la génération de pack personnalisé par client est chère sur le CPU du serveur, donc certains sites GIT importants le désactivent).

J'espère que cela répond à votre question. Vraiment avec git c'est si simple que vous êtes étonné que ça marche du tout au début, alors quand vous en enveloppez la tête, vous devenez sérieusement impressionné. Seuls les programmeurs vraiment géniaux peuvent écrire quelque chose de si simple mais qui fonctionne si bien car ils peuvent voir la simplicité là où la plupart des programmeurs ne peuvent voir que la complexité.

Niall

+0

Selon la page de manuel, 'git gc' fonctionne' git repack', donc dire que les deux sont totalement différents semble off. De plus, les deux premiers exemples (tous les deux ayant un compte "réutilisé" différent de zéro) proviennent d'un dépôt qui n'a qu'un seul paquet, donc votre explication n'a pas de sens pour moi. –

+1

Il y a du repack git et il y a du git repack - git gc si je me souviens fait un "light" repack. En ce qui concerne le nombre réutilisé, je base ma réponse sur la recherche d'un bug dans dulwich où les refs "externes à ce pack" ne sont pas satisfaits et dulwich est entré dans une boucle infinie. J'admettrai volontiers que je n'ai pas examiné le code git pour m'assurer que réutilisé signifie vraiment ce que je pense que cela signifie. –

+0

En ce qui concerne les comptes réutilisés ne passant pas à zéro, essayez git repack -a pour forcer un repack complet. J'ai édité ma réponse pour clarifier ce que je voulais dire par «repack complet». Essayez également d'augmenter la fenêtre et la profondeur pendant un reconditionnement complet (voir http://linux.die.net/man/1/git-repack). Pour un gros dépôt, certains objets réutilisés tombés à l'extérieur de la fenêtre peuvent rester. –

Questions connexes