Gibt es angesichts des Hash eines Blobs eine Möglichkeit, eine Liste der Commits zu erhalten, die diesen Blob in ihrem Baum haben?
git
version-control
Schreibgeschützt
quelle
quelle
git hash-object
oder zurückgegeben wirdsha1("blob " + filesize + "\0" + data)
, und nicht einfach die Summe des Blob-Inhalts.git log --follow filepath
(und diesen verwenden, um die Lösung von Aristoteles zu beschleunigen, wenn Sie möchten).~/.bin
und benennen Sie esgit-find-object
. Sie können es dann mit verwendengit find-object
.git describe <hash>
: Siehe meine Antwort unten .Antworten:
In beiden folgenden Skripten wird SHA1 des Blobs als erstes Argument und danach optional alle Argumente verwendet,
git log
die verstanden werden. ZB--all
in allen Zweigen anstatt nur in dem aktuellen-g
zu suchen oder im Reflog zu suchen oder was auch immer Sie möchten.Hier ist es als Shell-Skript - kurz und bündig, aber langsam:
Und eine optimierte Version in Perl, immer noch ziemlich kurz, aber viel schneller:
quelle
git rev-parse --verify $theprefix
my $blob_arg = shift; open my $rev_parse, '-|', git => 'rev-parse' => '--verify', $blob_arg or die "Couldn't open pipe to git-rev-parse: $!\n"; my $obj_name = <$rev_parse>; chomp $obj_name; close $rev_parse or die "Couldn't expand passed blob.\n"; $obj_name eq $blob_arg or print "(full blob is $obj_name)\n";
obj_name="$1" shift git log --all --pretty=format:'%T %h %s %n' -- "$@" | while read tree commit cdate subject ; do if [ -z $tree ] ; then continue fi if git ls-tree -r $tree | grep -q "$obj_name" ; then echo "$cdate $commit $@ $subject" fi done
--all
als zusätzliches Argument. (In Fällen wie dem Löschen einer großen Datei aus dem Repo-Verlauf ist es wichtig, alle Commits repo-weit zu finden .)Leider waren die Skripte für mich etwas langsam, so dass ich etwas optimieren musste. Zum Glück hatte ich nicht nur den Hash, sondern auch den Pfad einer Datei.
quelle
<hash>
angegebenen Wert haben möchte<path>
, funktioniert das Entfernen des<path>
Arguments aus demgit log
Testament. Das erste zurückgegebene Ergebnis ist das gewünschte Commit.Mit Git 2.16 (Q1 2018)
git describe
wäre dies eine gute Lösung, da gelernt wurde, Bäume tiefer zu graben, um ein<commit-ish>:<path>
Objekt zu finden , das sich auf ein bestimmtes Blob-Objekt bezieht.Siehe Commit 644eb60 , Commit 4dbc59a , Commit cdaed0c , Commit c87b653 , Commit ce5b6f9 (16. November 2017) und Commit 91904f5 , Commit 2deda00 (02. November 2017) von Stefan Beller (
stefanbeller
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 556de1a , 28. Dezember 2017)Das heißt, die
git describe
Manpage ergänzt die Zwecke dieses Befehls:Aber:
quelle
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print substr($0,6)}' | sort --numeric-sort --key=2 -r | head -n 20
, was Ihnen die 20 größten Blobs zurückgibt. Dann können Sie die Blob-ID von der obigen Ausgabe an übergebengit describe
. Arbeitete als Zauber! Vielen Dank!Ich dachte, dies wäre eine allgemein nützliche Sache, also schrieb ich ein kleines Perl-Skript, um es zu tun:
Ich werde das auf Github stellen, wenn ich heute Abend nach Hause komme.
Update: Es sieht so aus, als hätte dies bereits jemand getan . Dieser verwendet die gleiche allgemeine Idee, aber die Details sind unterschiedlich und die Implementierung ist viel kürzer. Ich weiß nicht, was schneller wäre, aber die Leistung spielt hier wahrscheinlich keine Rolle!
Update 2: Für das, was es wert ist, ist meine Implementierung um Größenordnungen schneller, insbesondere für ein großes Repository. Das
git ls-tree -r
tut wirklich weh.Update 3: Ich sollte beachten, dass meine obigen Leistungskommentare für die Implementierung gelten, die ich oben im ersten Update verlinkt habe. Die Implementierung von Aristoteles ist vergleichbar mit meiner. Weitere Details in den Kommentaren für diejenigen, die neugierig sind.
quelle
git rev-parse $commit^{}
Während die ursprüngliche Frage nicht danach fragt, halte ich es für nützlich, auch den Staging-Bereich zu überprüfen, um festzustellen, ob auf einen Blob verwiesen wird. Ich habe das ursprüngliche Bash-Skript geändert, um dies zu tun, und in meinem Repository festgestellt, was auf einen beschädigten Blob verweist:
quelle
Also ... ich musste alle Dateien über einem bestimmten Limit in einem Repo mit einer Größe von über 8 GB und über 108.000 Revisionen finden. Ich habe Aristoteles 'Perl-Skript zusammen mit einem Ruby-Skript angepasst, um diese vollständige Lösung zu erreichen.
Zuerst,
git gc
Führen Sie dies aus, um sicherzustellen, dass sich alle Objekte in Packdateien befinden. Wir scannen keine Objekte, die sich nicht in Packdateien befinden.Weiter Führen Sie dieses Skript aus, um alle Blobs über CUTOFF_SIZE-Bytes zu suchen. Erfassen Sie die Ausgabe in einer Datei wie "large-blobs.log".
Bearbeiten Sie als Nächstes die Datei, um alle Blobs zu entfernen, auf die Sie nicht warten, und die INPUT_THREAD-Bits oben. Wenn Sie nur noch Zeilen für die sha1s haben, die Sie suchen möchten, führen Sie das folgende Skript wie folgt aus:
Wo das
git-find-blob
Skript unten ist.Die Ausgabe sieht folgendermaßen aus:
Und so weiter. Jedes Commit, das eine große Datei in seinem Baum enthält, wird aufgelistet. Wenn Sie
grep
die Zeilenuniq
entfernen, die mit einer Registerkarte beginnen, und dies , haben Sie eine Liste aller Pfade, die Sie filtern und entfernen können, oder Sie können etwas Komplizierteres tun.Lassen Sie mich noch einmal wiederholen: Dieser Prozess lief erfolgreich auf einem 10-GB-Repo mit 108.000 Commits. Es hat viel länger gedauert, als ich vorhergesagt hatte, als ich mit einer großen Anzahl von Blobs lief, obwohl ich über 10 Stunden sehen muss, ob das Memorize-Bit funktioniert ...
quelle
-- --all
. (Es ist wichtig, alle Commits repo-weit zu finden, wenn eine große Datei gründlich aus dem Repo-Verlauf gelöscht wird .)Neben dem
git describe
, dass ich in meiner vorherigen Antwort erwähnt ,git log
undgit diff
profitiere jetzt auch von der „--find-object=<object-id>
“ Option , die Ergebnisse auf Änderungen zu beschränken , die das genannte Objekt beinhalten.Das ist in Git 2.16.x / 2.17 (Q1 2018)
Siehe Commit 4d8c51a , Commit 5e50525 , Commit 15af58c , Commit cf63051 , Commit c1ddc46 , Commit 929ed70 (04. Januar 2018) von Stefan Beller (
stefanbeller
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit c0d75f0 , 23. Januar 2018)quelle