Git - comment lister tous les objets dans la base de données
-
27-10-2019 - |
Question
Y at-il une meilleure façon d'obtenir une liste brute de SHA1s pour tous les objets dans un dépôt que de faire ls .git/objects/??/\*
et cat .git/objects/pack/*.idx | git show-index
?
Je sais à propos git rev-list --all
mais que les listes que commettent des objets qui sont référencés par .git / refs, et je suis à la recherche de tout , y compris les objets non référencés qui sont créés par git-hachage objet, git -mktree etc.
La solution
Modifier Aristote affiché encore mieux réponse, qui devrait être marqué comme correct.
Modifier le script contenait une erreur de syntaxe, manquant antislash à la fin de la ligne grep -v
La réponse de Mark a travaillé pour moi, après quelques modifications:
-
--git-dir
occasion au lieu de--show-cdup
pour soutenir repo nus - erreur Evité quand il n'y a pas de paquets
-
perl
Utilisé parce que OS X Mountain-lased
de style BSD Lion ne supporte pas-r
#!/bin/sh
set -e
cd "$(git rev-parse --git-dir)"
# Find all the objects that are in packs:
find objects/pack -name 'pack-*.idx' | while read p ; do
git show-index < $p | cut -f 2 -d ' '
done
# And now find all loose objects:
find objects/ \
| egrep '[0-9a-f]{38}' \
| grep -v /pack/ \
| perl -pe 's:^.*([0-9a-f][0-9a-f])/([0-9a-f]{38}):\1\2:' \
;
Autres conseils
Essayez
git rev-list --objects --all
Modifier Josh a fait un bon point:
git rev-list --objects -g --no-walk --all
objets liste accessible à partir de l'arbitre-journaux.
Pour voir tous les objets commits inatteignables ainsi:
git rev-list --objects --no-walk \
$(git fsck --unreachable |
grep '^unreachable commit' |
cut -d' ' -f3)
Mettre tous ensemble, vraiment obtenir tous les objets dans le format de sortie de rev-list --objects
, vous avez besoin quelque chose comme
{
git rev-list --objects --all
git rev-list --objects -g --no-walk --all
git rev-list --objects --no-walk \
$(git fsck --unreachable |
grep '^unreachable commit' |
cut -d' ' -f3)
} | sort | uniq
Pour trier la sortie légèrement plus moyen utile (par chemin pour l'arbre / blobs, engage en premier) utiliser un | sort -k2
supplémentaire qui regroupera tous les différents blobs (révisions) pour les chemins identiques.
Je ne sais pas depuis quand cette option existe mais vous pouvez
git cat-file --batch-check --batch-all-objects
Cela vous donne, selon la page de manuel,
tous les objets dans le référentiel et les magasins d'objets alternative ( non seulement des objets accessibles )
(Souligné par l'auteur).
Par défaut donne le type d'objet et la taille de chaque ensemble avec hachage, mais vous pouvez facilement supprimer ces informations, par exemple avec
git cat-file --batch-check --batch-all-objects | cut -d' ' -f1
ou en donnant un format personnalisé à --batch-check
.
Ceci est un plus juste, plus simple et plus rapide interprétation du script des réponses par Mark et par willkill .
-
Il utilise
rev-parse --git-path
pour trouver le répertoireobjects
même dans une configuration plus complexe dépôt Git (par exemple dans une situation multi-worktree ou autres joyeusetés). -
Il évite toute utilisation inutile de
find
,grep
,perl
,sed
. -
Si des œuvres avec élégance, même si vous avez aucun objet ou aucun paquets en vrac (ou non plus ... si vous avez tendance à exécuter sur un dépôt frais).
-
Il ne nécessite toutefois un Bash de ce millénaire ?? (2.02 ou plus récent, en particulier, pour le bit de
extglob
).
Partager et apprécier.
#!/bin/bash
set -e
shopt -s nullglob extglob
cd "`git rev-parse --git-path objects`"
# packed objects
for p in pack/pack-*([0-9a-f]).idx ; do
git show-index < $p | cut -f 2 -d ' '
done
# loose objects
for o in [0-9a-f][0-9a-f]/*([0-9a-f]) ; do
echo ${o/\/}
done
Je ne sais pas d'une façon évidemment mieux que de simplement regarder tous les fichiers en vrac d'objets et les indices de tous les fichiers du pack. Le format du dépôt git est très stable, et avec cette méthode, vous ne devez pas compter sur avoir exactement les bonnes options à git fsck
, qui est classé comme la porcelaine. Je pense que cette méthode est plus rapide, aussi bien. Le script suivant montre tous les objets dans un référentiel:
#!/bin/sh
set -e
cd "$(git rev-parse --show-cdup)"
# Find all the objects that are in packs:
for p in .git/objects/pack/pack-*.idx
do
git show-index < $p | cut -f 2 -d ' '
done
# And now find all loose objects:
find .git/objects/ | egrep '[0-9a-f]{38}' | \
sed -r 's,^.*([0-9a-f][0-9a-f])/([0-9a-f]{38}),\1\2,'
(Ma version originale de ce script a été basé sur un GitHub essentiel .
La commande git cat-file --batch-check --batch-all-objects
, suggéré dans Erki Der Loony 's answer , peut être fait plus rapide avec la nouvelle option Git 2,19 (Q3 2018) --unordered
.
L'API itérer sur tous les objets appris à éventuellement des objets de la liste dans l'ordre où ils apparaissent dans packfiles , qui aide à la localité d'accès si l'appelant accède à ces objets pendant que sont dénombrées objets.
Voir commettre 0889aae , commit 79ed0a5 , engager ced9fff (14 août 2018), et engager 0750bb5 , commit b1adb38 , commettras aa2f5ef , commit 736eb88 , commettras 8b36155 , engager a7ff6f5 , commit 202e7f1 (10 août 2018) par Jeff roi (peff
) .
(Fusionné par Junio ??Hamano C - gitster
- commit 0c54cda 20 Aou 2018)
cat-file
: support sortie "unordered
" pour--batch-all-objects
Si vous allez accéder au contenu de chaque objet dans un packfile, il est généralement beaucoup plus efficace de le faire pour pack, plutôt que dans l'ordre de hachage . Cela augmente la localité d'accès dans le packfile, ce qui est plus favorable à la cache de base delta, puisque les puts packfile deltas liés à côté de l'autre. En revanche, l'ordre de hachage est effectivement aléatoire, puisque le SHA1 n'a pas discernable relation avec le contenu.
Ce correctif introduit une option « de
--unordered
» àcat-file
qui itère sur les paquets en pack ordre sous le capot. Vous pouvez voir les résultats lorsque le dumping tout le contenu du fichier:$ time ./git cat-file --batch-all-objects --buffer --batch | wc -c 6883195596 real 0m44.491s user 0m42.902s sys 0m5.230s $ time ./git cat-file --unordered \ --batch-all-objects --buffer --batch | wc -c 6883195596 real 0m6.075s user 0m4.774s sys 0m3.548s
Même sortie, un ordre différent, de façon plus rapide. La même vitesse de connexion s'applique même si vous finissez par accéder au contenu de l'objet dans un différents processus, comme:
git cat-file --batch-all-objects --buffer --batch-check | grep blob | git cat-file --batch='%(objectname) %(rest)' | wc -c
Ajout "
--unordered
" à la première commande supprime le moteur d'exécutiongit.git
de 24s à 3.5s.Note Side: il y a effectivement plus disponibles pour speedups tout faire maintenant en cours. Puisque nous restituent le contenu de l'objet lors de l'itération pack réelle, nous savons où trouver l'objet et pourrait sauter la recherche supplémentaire fait par
oid_object_info()
. Ce patch s'arrête de cette optimisation puisque l'API sous-jacente est pas prête pour nous de faire ce genredes demandes directes.Donc, si
--unordered
est tellement mieux, pourquoi ne pas faire défaut? Deux raisons:
Nous avons promis dans la documentation sorties
--batch-all-objects
dans l'ordre de hachage. Depuiscat-file
est la plomberie, les gens peuvent se fier à ce défaut, et nous ne pouvons le changer.Il est en fait plus lent pour certains cas. Nous devons calculer le pack revindex marcher pour pack. Et notre étape de déduplication utilise un oidset, plutôt que d'un tri et dedup, ce qui peut finir par être plus cher.
Si nous sommes en train d'accéder au type et la taille de chaque objet, par exemple, comme:
git cat-file --batch-all-objects --buffer --batch-check
mon best-of-cinq timings de cache chaud vont de 900ms à 1100ms en utilisant
--unordered
. Bien qu'il soit possible dans un cache de froid ou sous la pression de la mémoire que nous pourrions faire mieux, puisque nous aurions une meilleure localité du packfile.Une dernière question: pourquoi est-il «
--unordered
» et non «--pack-order
»? La réponse est à nouveau deux fois:
« ordre pack » est pas une chose bien définie dans l'ensemble des objets. Nous frapper des objets en vrac, ainsi que des objets en plusieurs paquets, et la commande que nous promet est dans les un seul paquet. Le reste est apparemment aléatoire.
Le point est l'optimisation ici. Donc, nous ne voulons pas promettre une commande particulière, mais seulement de dire que nous allons choisir un ordre qui est susceptible d'être efficace pour accéder au contenu de l'objet. Cela laisse la porte ouverte pour d'autres changements dans l'avenir sans avoir à ajouter une autre option de compatibilité
Il est encore plus rapide dans Git 2.20 (Q4 2018) avec:
Voir commettre 8c84ae6 , commit 8b2f8cb , commit 9249ca2 , engager 22a1646 , commit bf73282 (4 octobre 2018) par René Scharfe (rscharfe
) .
(Fusionné par Junio ??Hamano C - gitster
- commit 82d0a8c 19 oct 2018)
oidset
: utilisationkhash
réimplémentons
oidset
utilisantkhash.h
afin de réduire son encombrement mémoire et de le rendre plus rapide.Performance d'une commande qui contrôle principalement pour des objets en double à l'aide un oidset, avec
master
et Clang 6.0.1:$ cmd="./git-cat-file --batch-all-objects --unordered --buffer --batch-check='%(objectname)'" $ /usr/bin/time $cmd >/dev/null 0.22user 0.03system 0:00.25elapsed 99%CPU (0avgtext+0avgdata 48484maxresident)k 0inputs+0outputs (0major+11204minor)pagefaults 0swaps $ hyperfine "$cmd" Benchmark #1: ./git-cat-file --batch-all-objects --unordered --buffer --batch-check='%(objectname)' Time (mean ± σ): 250.0 ms ± 6.0 ms [User: 225.9 ms, System: 23.6 ms] Range (min … max): 242.0 ms … 261.1 ms
Et avec ce patch:
$ /usr/bin/time $cmd >/dev/null 0.14user 0.00system 0:00.15elapsed 100%CPU (0avgtext+0avgdata 41396maxresident)k 0inputs+0outputs (0major+8318minor)pagefaults 0swaps $ hyperfine "$cmd" Benchmark #1: ./git-cat-file --batch-all-objects --unordered --buffer --batch-check='%(objectname)' Time (mean ± σ): 151.9 ms ± 4.9 ms [User: 130.5 ms, System: 21.2 ms] Range (min … max): 148.2 ms … 170.4 ms
2,21 Git (Q1 2019) optimise en outre l'codepath d'écrire commit-graphe, par suivant le schéma habituel de visiter des objets pour en paquet.
Voir engager d7574c9 (19 janvier 2019) par Ævar Arnfjord Bjarmason (avar
)
(Fusionné par Junio ??Hamano C - gitster
- commit 04d67b6 , 5 février 2019)
optimiser légèrement l'étape « commit-graphe écriture » en utilisant
FOR_EACH_OBJECT_PACK_ORDER
avecfor_each_object_in_pack()
.
Derrick Stolee a ses propres tests sous Windows représentant 2% amélioration avec un haut degré de précision.
2,23 Git (Q3 2019) améliore " git rev-list --objects
" qui appris avec l'option « --no-object-names
» pour écraser le chemin de l'objet qui est utilisé comme un indice de regroupement pour pack-objets.
Voir commettras 42357b4 (19 juin 2019) par Emily Shaffer (nasamuffin
)
(Fusionné par Junio ??Hamano C - gitster
- commit f4f7e75 , 9 juillet 2019)
rev-list
: enseigner--no-object-names
pour permettre la tuyauteriePermettre l'analyse syntaxique plus facile par
decat-file
en donnant une option d'imprimer rev-list que l'OID d'un objet non-commit sans aucune information supplémentaire.
Ceci est une cale à court terme; plus tard, devrait être enseignérev-list
comment imprimer les types d'objets qu'il trouve dans un format similaire àcat-file
.Avant ce commit, la sortie de
rev-list
devait être massé avant d'être canalisé pour chat fichier, comme suit:git rev-list --objects HEAD | cut -f 1 -d ' ' | git cat-file --batch-check
Cela était particulièrement inattendu lorsqu'il s'agit d'arbres à racines, comme invisible existe des espaces à la fin de l'OID:
git rev-list --objects --filter=tree:1 --max-count=1 HEAD | xargs -I% echo "AA%AA"
Maintenant, il peut être canalisé directement, comme dans le cas de test ajouté:
git rev-list --objects --no-object-names HEAD | git cat-file --batch-check
qui est la différence entre:
vonc@vonvb:~/gits/src/git$ git rev-list --objects HEAD~1..
9d418600f4d10dcbbfb0b5fdbc71d509e03ba719
590f2375e0f944e3b76a055acd2cb036823d4b44
55d368920b2bba16689cb6d4aef2a09e8cfac8ef Documentation
9903384d43ab88f5a124bc667f8d6d3a8bce7dff Documentation/RelNotes
a63204ffe8a040479654c3e44db6c170feca2a58 Documentation/RelNotes/2.23.0.txt
Et, avec --no-object-name
:
vonc@vonvb:~/gits/src/git$ git rev-list --objects --no-object-names HEAD~1..
9d418600f4d10dcbbfb0b5fdbc71d509e03ba719
590f2375e0f944e3b76a055acd2cb036823d4b44
55d368920b2bba16689cb6d4aef2a09e8cfac8ef
9903384d43ab88f5a124bc667f8d6d3a8bce7dff
a63204ffe8a040479654c3e44db6c170feca2a58
Une autre option utile est d'utiliser git verify-pack -v <packfile>
listes de verify-pack -v
tous les objets dans la base de données ainsi que leur type d'objet.