Domanda

C'è un modo migliore di ottenere un raw elenco di SHA1s per TUTTI gli oggetti in un repository che fare ls .git/objects/??/\* e cat .git/objects/pack/*.idx | git show-index?

Conosco git rev-list --all ma solo elenchi di commettere gli oggetti a cui fa riferimento .git/refs, e sto cercando tutto tra unreferenced gli oggetti che vengono creati da git-hash-oggetto, git-mktree etc.

È stato utile?

Soluzione

Modificare: Aristotele pubblicato Una risposta ancora migliore, che dovrebbe essere contrassegnato come corretto.

Modificare: Lo script conteneva un errore di sintassi, mancante di retroscena alla fine del grep -v linea

La risposta di Mark ha funzionato per me, dopo alcune modifiche:

  • Usato --git-dir invece di --show-cdup Per supportare Repos Bare
  • Errore evitato quando non ci sono pacchetti
  • Usato perl Perché in stile BSD di Os X Mountain Lion sed non supporta -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:' \
;

Altri suggerimenti

Provare

 git rev-list --objects --all

Modificare Josh ha fatto un buon punto:

 git rev-list --objects -g --no-walk --all

Elenca gli oggetti raggiungibili dai ref-logs.

Per vedere anche tutti gli oggetti in commit irraggiungibili:

 git rev-list --objects --no-walk \
      $(git fsck --unreachable |
        grep '^unreachable commit' |
        cut -d' ' -f3)

Mettendo tutto insieme, a veramente Ottieni tutti gli oggetti nel formato di output di rev-list --objects, hai bisogno di qualcosa di simile

{
    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

Per ordinare l'output in modo leggermente più utile (tramite Path for Tree/Blobs, si impegna prima) Utilizzare un ulteriore | sort -k2 che raggrupperà tutte le diverse chiazze (revisioni) per percorsi identici.

Non lo so da quando questa opzione esiste ma puoi

git cat-file --batch-check --batch-all-objects

Questo ti dà, secondo la pagina uomo,

Tutti gli oggetti nel repository e in qualsiasi negozio di oggetti alternati (non solo oggetti raggiungibili)

(enfasi la mia).

Per impostazione predefinita, questo produce il tipo di oggetto e le sue dimensioni insieme ad ogni hash, ma puoi facilmente rimuovere queste informazioni, ad es.

git cat-file --batch-check --batch-all-objects | cut -d' ' -f1

o dando un formato personalizzato a --batch-check.

Questa è una interpretazione più corretta, più semplice e più veloce dello script dalle risposte di Mark e di Willkill.

  • Utilizza rev-parse --git-path per trovare il objects Directory anche in una configurazione del repository Git più complesso (ad es. In una situazione multi-lavoro o quant'altro).

  • Evita ogni uso inutile di find, grep, perl, sed.

  • Se funziona con grazia anche se non hai oggetti sciolti o nessun pacchetto (o nessuno dei due ... se sei propenso a eseguirlo su un nuovo repository).

  • Tuttavia, richiede una festa da questo millennio 😊 (2.02 o più recente, in particolare per il extglob morso).

Condividi e divertiti.

#!/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

Non conosco un modo ovviamente migliore che guardare tutti i file di oggetti sciolti e gli indici di tutti i file pack. Il formato del repository git è molto stabile e con questo metodo non devi fare affidamento sull'avere esattamente le opzioni giuste per git fsck, che è classificato come porcellana. Penso che anche questo metodo sia più veloce. Il seguente script mostra tutti gli oggetti in un repository:

#!/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,'

(La mia versione originale di questo script era basata su Questo utile script per trovare gli oggetti più grandi nei file del pacchetto, ma sono passato all'uso git show-index, come suggerito nella tua domanda.)

Ho trasformato questa sceneggiatura in un gist github.

Il git cat-file --batch-check --batch-all-objects comando suggerito in Erki Der Matto's risposta, può essere fatto più veloce con il nuovo Git 2.19 (Q3 2018) opzione --unordered.

L'API per iterare su tutti gli oggetti imparato a facoltativamente elenco di oggetti nell'ordine in cui appaiono nel packfiles, che aiuta la località di accesso se il visitatore accede a questi oggetti come gli oggetti vengono enumerati.

Vedere commettere 0889aae, commettere 79ed0a5, commettere 54d2f0d, commettere ced9fff (14 Agosto 2018), e commettere 0750bb5, commettere b1adb38, commettere aa2f5ef, commettere 736eb88, commettere 8b36155, commettere a7ff6f5, commettere 202e7f1 (10 Agosto 2018) da Jeff King (peff). (Fusa per Junio C Hamano -- gitster -- in commettere 0c54cda, 20 Agosto 2018)

cat-file:il supporto "unordered"uscita per --batch-all-objects

Se avete intenzione di accedere al contenuto di ogni oggetto in un packfile, è generalmente molto più efficiente per farlo pack ordine, piuttosto che in ordine hash.Che aumenta la frazione di accesso entro il packfile, che a sua volta è più amichevole con la base delta cache, poiché il packfile mette relative delta accanto all'altro.Per contro, hash ordine in modo efficace è casuale, dal momento che la sha1 ha alcuna relazione al contenuto.

Questa patch introduce un "--unordered"l'opzione per cat-file che scorre pack pack-ordine sotto il cofano.Si possono vedere i risultati quando dumping tutto il contenuto del file:

$ 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

Stessa uscita, ordine diverso, molto più veloce.La stessa velocità che si applica anche se si finisce per l'accesso all'oggetto contenuto in un il processo differente, come:

git cat-file --batch-all-objects --buffer --batch-check |
grep blob |
git cat-file --batch='%(objectname) %(rest)' |
wc -c

L'aggiunta di "--unordered"per il primo comando gocce di runtime in git.git dal 24 al 3,5 s.

Nota a margine:in realtà ci sono ulteriori speedups disponibile per fare tutto in-process ora.Visto che siamo output il contenuto di oggetti durante i pack iterazione, sappiamo dove trovare l'oggetto e potrebbe saltare l'extra di ricerca fatto da oid_object_info().Questa patch si ferma a corto di ottimizzazione che poiché il sottostante API non è pronto per noi a fare questi tipi di richieste dirette.

Quindi, se --unordered è tanto meglio, perché non renderlo predefinito?Due motivi:

  1. Abbiamo promesso nella documentazione che --batch-all-objects uscite in hash ordine.Dal cat-file è l'idraulica, la gente può fare affidamento su quella di default, e non possiamo cambiarlo.

  2. In realtà più lento per alcuni casi.Dobbiamo calcolare il pack revindex a piedi in pack ordine.E il nostro de-duplicazione passo utilizza un oidset, piuttosto che una sorta-e-dedup, che alla fine può essere più costoso.

Se siamo solo accedendo con il tipo e la dimensione di ogni oggetto, come ad esempio:

git cat-file --batch-all-objects --buffer --batch-check

il mio best-of-cinque calda cache tempi andare da 900ms per 1100ms utilizzando --unordered.Anche se è possibile in un freddo cache o sotto pressione della memoria che si poteva fare di meglio, visto che ci sarebbe la migliore località all'interno del packfile.

E un'ultima domanda:perché è "--unordered"e non "--pack-order"?La risposta è di nuovo due volte:

  1. "pack ordine" non è ben definito cosa per tutta la serie di oggetti.Stiamo colpendo gli oggetti sciolti, così come gli oggetti in confezioni multiple, e l'unico ordine siamo promettente è all'interno un unico pack.Il resto è apparentemente casuali.

  2. Il punto qui è l'ottimizzazione.Quindi non vogliamo promettere alcun particolare ordine, ma solo per dire che saremo noi a scegliere un ordinamento che è probabile che sia efficiente per l'accesso all'oggetto contenuto.Che lascia la porta aperta per ulteriori modifiche in futuro, senza dover aggiungere un'altra opzione di compatibilità


E ' anche più veloce nella tabella 2.20 (4t 2018) con:

Vedere commettere 8c84ae6, commettere 8b2f8cb, commettere 9249ca2, commettere 22a1646, commettere bf73282 (04 Ottobre 2018) da René Scharfe (rscharfe).
(Fusa per Junio C Hamano -- gitster -- in commettere 82d0a8c, 19 Ottobre 2018)

oidset:utilizzare khash

Reimplementare oidset utilizzando khash.h per ridurre la sua impronta di memoria e renderlo più veloce.

Esecuzione di un comando che principalmente i controlli per duplicare gli oggetti utilizzando un oidset, con master e 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

E con questa 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

Git 2.21 (Q1 2019) ottimizza ulteriormente il codepath per scrivere commit-grafico, da seguendo il consueto schema di visitare gli oggetti in-pack ordine.

Vedere commettere d7574c9 (19 gennaio 2019) da Ævar Arnfjörð Bjarmason (avar).
(Fusa per Junio C Hamano -- gitster -- in commettere 04d67b6, 05 Febbraio 2019)

Leggermente ottimizzare il "commit-grafico a scrivere" passaggio utilizzando FOR_EACH_OBJECT_PACK_ORDER con for_each_object_in_pack().
Derrick Stolee fatto il suo test su Windows mostrando un 2% miglioramento, con un alto grado di precisione.


Git 2.23 (Q3 2019) migliora "git rev-list --objects"che ha appreso con "--no-object-names"la possibilità di squelch il percorso dell'oggetto che viene utilizzato come un raggruppamento suggerimento per pack-oggetti.

Vedere commettere 42357b4 (19 Giugno 2019) da Emily Shaffer (nasamuffin).
(Fusa per Junio C Hamano -- gitster -- in commettere f4f7e75, 09 Lug 2019)

rev-list:insegnare --no-object-names per attivare tubazioni

Consentire una più facile analisi da cat-file dando rev-elenco un'opzione per la stampa solo l'OID di un non-oggetto commit senza ulteriori informazioni.
Questo è un breve termine di spessore;in seguito, rev-list dovrebbe essere insegnato come stampa i tipi di oggetti che si trova in un formato simile a cat-file's.

Prima di questa operazione, l'uscita dal rev-list bisogno di essere massaggiato prima di essere reindirizzato a cat-file, in questo modo:

git rev-list --objects HEAD | cut -f 1 -d ' ' |
    git cat-file --batch-check

Questo è stato particolarmente inaspettato quando ha a che fare con la radice di alberi, come un invisibile spazio esistente al fine di OID:

git rev-list --objects --filter=tree:1 --max-count=1 HEAD |
    xargs -I% echo "AA%AA"

Ora, può essere convogliata direttamente, come nei casi di test:

git rev-list --objects --no-object-names HEAD | git cat-file --batch-check

Quindi che differenza c'è tra:

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

E, con --no-object-name:

vonc@vonvb:~/gits/src/git$ git rev-list --objects --no-object-names HEAD~1..
9d418600f4d10dcbbfb0b5fdbc71d509e03ba719
590f2375e0f944e3b76a055acd2cb036823d4b44
55d368920b2bba16689cb6d4aef2a09e8cfac8ef
9903384d43ab88f5a124bc667f8d6d3a8bce7dff
a63204ffe8a040479654c3e44db6c170feca2a58

Un'altra opzione utile è usare git verify-pack -v <packfile>

verify-pack -v Elenca tutti gli oggetti nel database insieme al loro tipo di oggetto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top