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.

Était-ce utile?

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-la sed 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épertoire objects 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écution git.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:

  1. Nous avons promis dans la documentation sorties --batch-all-objects dans l'ordre de hachage. Depuis cat-file est la plomberie, les gens peuvent se fier à ce défaut, et nous ne pouvons le changer.

  2. 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:

  1. « 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.

  2. 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: utilisation khash

réimplémentons oidset utilisant khash.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 avec for_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 tuyauterie

Permettre l'analyse syntaxique plus facile par cat-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 à

de 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top