Frage

Gibt es eine bessere Möglichkeit, eine Rohliste der SHA1s für ALLE Objekte in einem Repository zu erhalten, als dies zu tun? ls .git/objects/??/\* Und cat .git/objects/pack/*.idx | git show-index?

ich weiss Bescheid git rev-list --all Aber das listet nur Commit-Objekte auf, auf die von .git/refs verwiesen wird, und die ich suche alles einschließlich nicht referenzierter Objekte, die von git-hash-object, git-mktree usw. erstellt werden.

War es hilfreich?

Lösung

Bearbeiten: Aristoteles Gesendet Eine noch bessere Antwort, was als korrekt markiert werden sollte.

Bearbeiten: Das Skript enthielt einen Syntaxfehler, der am Ende des grep -v Linie

Marks Antwort von Mark funktionierte nach ein paar Modifikationen für mich:

  • Gebraucht --git-dir Anstatt von --show-cdup Bare Repos zu unterstützen
  • Vermieden Fehler, wenn es keine Packs gibt
  • Gebraucht perl Weil OS X Mountain Lion's BSD-Stil-Stil sed unterstützt nicht -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:' \
;

Andere Tipps

Versuchen

 git rev-list --objects --all

Bearbeiten Josh machte einen guten Punkt:

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

Listen Sie Objekte aus, die aus den Ref-Logs erreichbar sind.

Alle Objekte auch in unerreichbaren Commits zu sehen:

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

Alles zusammenfügen, zu Ja wirklich Holen Sie sich alle Objekte im Ausgabeformat von rev-list --objects, du brauchst so etwas wie

{
    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

Um die Ausgabe auf etwas nützlichere Weise zu sortieren (nach Pfad für Baum/Blobs, zuerst) verwenden Sie eine zusätzliche | sort -k2 die alle verschiedenen Blobs (Revisionen) für identische Pfade gruppieren.

Ich weiß nicht, seit diese Option existiert, aber Sie können es können

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

Dies gibt Ihnen nach der Mannseite,

alle Objekte im Repository und alle alternativen Objektspeicher (Nicht nur erreichbare Objekte)

(Hervorhebung meiner).

Standardmäßig ergibt dies den Objekttyp und die Größe zusammen mit jedem Hash, aber Sie können diese Informationen leicht entfernen, z. B. mit

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

oder durch Geben eines benutzerdefinierten Formats an --batch-check.

Dies ist eine korrektere, einfachere und schnellere Wiedergabe des Skripts aus den Antworten von Mark und von Willkill.

  • Es verwendet rev-parse --git-path um das zu finden objects Verzeichnis auch in einem komplexeren Git-Repository-Setup (z. B. in einer Multi-Worktree-Situation oder so weiter).

  • Es vermeidet alle unnötigen Gebrauch von find, grep, perl, sed.

  • Wenn Sie anmutig funktionieren, auch wenn Sie keine losen Objekte oder keine Packungen haben (oder auch nicht ... wenn Sie dazu geneigt sind, dies auf einem neuen Repository auszuführen).

  • Es erfordert jedoch eine Bash von diesem Jahrtausend 😊 (2.02 oder neuer, insbesondere für die extglob bisschen).

Teile und genieße.

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

Ich kenne keinen offensichtlich besseren Weg, als nur alle losen Objektdateien und Indizes aller Packdateien zu betrachten. Das Format des Git -Repositorys ist sehr stabil, und mit dieser Methode müssen Sie sich nicht darauf verlassen, genau die richtigen Optionen zu haben git fsck, was als Porzellan eingestuft wird. Ich denke, diese Methode ist auch schneller. Das folgende Skript zeigt alle Objekte in einem 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,'

(Meine Originalversion dieses Skripts basiert auf Dieses nützliche Skript, um die größten Objekte in Ihren Packdateien zu finden, aber ich wechselte zur Verwendung git show-index, wie in Ihrer Frage vorgeschlagen.)

Ich habe dieses Skript gemacht Ein Github -Gist.

Der git cat-file --batch-check --batch-all-objects Befehl, vorgeschlagen in Erki Der Loony'S Antwort, kann gemacht werden Schneller mit der neuen Option Git 2.19 (Q3 2018). --unordered.

Die API zum Durchlaufen aller erlernten Objekte Listen Sie optional Objekte in der Reihenfolge auf, in der sie in Packdateien erscheinen, was die Lokalität des Zugriffs erleichtert, wenn der Aufrufer auf diese Objekte zugreift, während Objekte aufgelistet werden.

Sehen Commit 0889aae, Commit 79ed0a5, Commit 54d2f0d, Commit ced9fff (14. August 2018) und begehen 0750bb5, Commit b1adb38, Commit aa2f5ef, Commit 736eb88, Commit 8b36155, Commit a7ff6f5, Commit 202e7f1 (10. August 2018) von Jeff King (peff). (Zusammengeführt von Junio ​​C Hamano -- gitster -- In Commit 0c54cda, 20. August 2018)

cat-file:Unterstützung "unordered" Ausgabe für --batch-all-objects

Wenn Sie auf den Inhalt jedes Objekts in einer Packdatei zugreifen möchten, Im Allgemeinen ist es viel effizienter, dies in der Pack-Reihenfolge zu tun, als in der Hash-Reihenfolge.Dadurch wird die Lokalität des Zugriffs innerhalb der Packdatei erhöht, was wiederum den Delta-Basis-Cache schont, da die Packdatei verwandte Deltas nebeneinander platziert.Im Gegensatz dazu ist die Hash -Ordnung effektiv zufällig, da der SHA1 keine erkennbare Beziehung zum Inhalt hat.

Dieser Patch führt ein „--unordered"Option zu cat-file das unter der Haube Pakete in der Paketreihenfolge durchläuft.Sie können die Ergebnisse sehen, wenn Sie den gesamten Dateiinhalt sichern:

$ 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

Gleiche Ausgabe, andere Reihenfolge, viel schneller.Die gleiche Beschleunigung gilt auch dann, wenn Sie in einem anderen Prozess auf den Objektinhalt zugreifen, z. B.:

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

Hinzufügen „--unordered" Beim ersten Befehl wird die Laufzeit abgelegt git.git von 24s bis 3,5s.

Randnotiz:Es gibt tatsächlich weitere Beschleunigungsmöglichkeiten, um alles jetzt im Prozess zu erledigen.Da wir den Objektinhalt während der eigentlichen Pack-Iteration ausgeben, wissen wir, wo sich das Objekt befindet, und können die zusätzliche Suche von durch überspringen oid_object_info().Mit diesem Patch wird diese Optimierung nicht erreicht, da die zugrunde liegende API nicht für solche direkten Anfragen bereit ist.

Also wenn --unordered ist so viel besser, warum nicht als Standard festlegen?Zwei Gründe:

  1. Das haben wir in der Dokumentation versprochen --batch-all-objects Gibt in Hash-Reihenfolge aus.Seit cat-file Da es sich um Sanitärinstallationen handelt, verlassen sich die Leute möglicherweise auf diese Standardeinstellung, und wir können sie nicht ändern.

  2. Es ist eigentlich Langsamer für einige Fälle.Wir müssen den Pack-Revindex berechnen, um in der Packreihenfolge zu laufen.Und unser Deduplizierungsschritt verwendet ein Oidset anstelle eines Sortierens und Dedupierens, was am Ende teurer sein kann.

Wenn wir beispielsweise nur auf den Typ und die Größe jedes Objekts zugreifen, so:

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

Meine Best-of-Five-Warm-Cache-Timings reichen von 900 ms bis 1100 ms --unordered.Bei einem Cold-Cache oder unter Speicherdruck ist es jedoch möglich, dass wir es besser machen könnten, da wir eine bessere Lokalität innerhalb der Packdatei hätten.

Und noch eine letzte Frage:warum ist es "--unordered" und nicht "--pack-order„?Die Antwort ist wiederum zweifach:

  1. „Packreihenfolge“ ist für die gesamte Menge von Objekten nicht klar definiert.Wir besorgen sowohl lose Gegenstände als auch Gegenstände in mehreren Packungen, und die einzige Bestellung, die wir versprechen, ist innerhalb eine einzelne Packung.Der Rest ist scheinbar zufällig.

  2. Hier geht es um Optimierung.Daher möchten wir keine bestimmte Reihenfolge versprechen, sondern nur sagen, dass wir eine Reihenfolge wählen werden, die für den Zugriff auf den Objektinhalt wahrscheinlich effizient ist.Dies lässt die Tür für weitere Änderungen in der Zukunft offen, ohne dass eine weitere Kompatibilitätsoption hinzugefügt werden muss


In Git 2.20 (Q4 2018) ist es noch schneller mit:

Sehen Commit 8c84ae6, Commit 8b2f8cb, Commit 9249ca2, Commit 22a1646, Commit bf73282 (04. Okt. 2018) von René Scharfe (rscharfe).
(Zusammengeführt von Junio ​​C Hamano -- gitster -- In Commit 82d0a8c, 19. Okt. 2018)

oidset:verwenden khash

Neuimplementierung oidset verwenden khash.h Um seinen Speicherpflichtzdruck zu reduzieren und es schneller zu machen.

Leistung eines Befehls, der hauptsächlich nach doppelten Objekten mit einem OIDSet überprüft, mit master und 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

Und mit diesem 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) optimiert weiter den Codepath, um das Komitee-Graph zu schreiben, indem sie dem üblichen Muster von Objekten in der In-Pack-Reihenfolge befolgt.

Sehen Commit d7574c9 (19. Januar 2019) von Ævar Arnfjörð Bjarmason (avar).
(Zusammengeführt von Junio ​​C Hamano -- gitster -- In Commit 04d67b6, 05.02.2019)

Optimieren Sie den Schritt „Commit-Graph Write“ leicht, indem Sie verwenden FOR_EACH_OBJECT_PACK_ORDER mit for_each_object_in_pack().
Derrick Stolee hat es getan seine eigenen Tests unter Windows zeigte eine Verbesserung von 2% mit einem hohen Maß an Genauigkeit.


Git 2.23 (Q3 2019) verbessert „git rev-list --objects„was gelernt hat mit“--no-object-names" Option zum Unterdrücken des Pfads zum Objekt, das als Gruppierungshinweis für Paketobjekte verwendet wird.

Sehen Commit 42357b4 (19. Juni 2019) von Emily Shaffer (nasamuffin).
(Zusammengeführt von Junio ​​C Hamano -- gitster -- In f4f7e75 begehen, 09.07.2019)

rev-list:unterrichten --no-object-names Rohrleitungen zu ermöglichen

Ermöglichen Sie eine einfachere Analyse durch cat-file Indem Sie die Rev-List eine Option geben, um nur die OID eines Nicht-Commit-Objekts ohne zusätzliche Informationen zu drucken.
Dies ist eine kurzfristige Unterlegscheibe;später, rev-list sollte gelehrt werden, wie man die Arten von Objekten druckt, die es in einem ähnlichen Format findet wie cat-file'S.

Vor diesem Commit ist die Ausgabe von rev-list musste massiert werden, bevor er nach Cat-File geleitet wurde, wie SO:

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

Dies war besonders unerwartet beim Umgang mit Wurzelbäumen, da am Ende des OID eine unsichtbare Whitespace existiert:

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

Jetzt kann es direkt weitergeleitet werden, wie im hinzugefügten Testfall:

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

Das ist also der Unterschied zwischen:

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

Und mit --no-object-name:

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

Eine weitere nützliche Option ist die Verwendung git verify-pack -v <packfile>

verify-pack -v Listet alle Objekte in der Datenbank zusammen mit ihrem Objekttyp auf.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top