Die in den Baumobjekten gespeicherten SHA1-Hashes (wie von zurückgegeben git ls-tree
) stimmen nicht mit den SHA1-Hashes des Dateiinhalts überein (wie von zurückgegeben sha1sum
)
$ git cat-file blob 4716ca912495c805b94a88ef6dc3fb4aff46bf3c | sha1sum
de20247992af0f949ae8df4fa9a37e4a03d7063e -
Wie berechnet git Datei-Hashes? Komprimiert es den Inhalt, bevor der Hash berechnet wird?
Antworten:
$ echo -e 'blob 14\0Hello, World!' | shasum 8ab686eafeb1f44702738c8b0f24f2567c36da6d
Quelle: http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html
quelle
echo 'Hello, World!' | git hash-object --stdin
. Optional können Sie angeben--no-filters
, um sicherzustellen, dass keine crlf-Konvertierung stattfindet, oder angeben--path=somethi.ng
, dass git den übergitattributes
(auch @ user420667) angegebenen Filter verwenden soll. Und-w
einreichen tatsächlich den Blob zu.git/objects
(wenn Sie sind in einem Git - Repo - Geschäfte).echo -e 'blob 16\0Hello, \r\nWorld!' | shasum
==echo -e 'Hello, \r\nWorld!' | git hash-object --stdin --no-filters
und es wird auch äquivalent zu\n
und 15.echo
Hängt eine neue Zeile an die Ausgabe an, die ebenfalls an git übergeben wird. Deshalb sind es 14 Zeichen. Um Echo ohne Zeilenumbruch zu verwenden, schreiben Sieecho -n 'Hello, World!'
Ich erweitere nur die Antwort durch
@Leif Gruenwoldt
und erläutere, was in der Referenz von enthalten ist@Leif Gruenwoldt
Mach es selbst..
Wie berechnet GIT seine Commit-Hashes?
Der Text
blob⎵
ist ein konstantes Präfix und\0
ist auch konstant und ist dasNULL
Zeichen. Das<size_of_file>
und<contents_of_file>
variieren je nach Datei.Siehe: Wie lautet das Dateiformat eines Git-Commit-Objekts?
Und das sind alle Leute!
Aber warte! Haben Sie bemerkt, dass dies
<filename>
kein Parameter ist, der für die Hash-Berechnung verwendet wird? Zwei Dateien können möglicherweise denselben Hash haben, wenn ihr Inhalt unabhängig von Datum und Uhrzeit ihrer Erstellung und ihrem Namen gleich ist. Dies ist einer der Gründe, warum Git Verschiebungen und Umbenennungen besser handhabt als andere Versionskontrollsysteme.Mach es selbst (ext)
Hinweis:
Der Link erwähnt nicht, wie das
tree
Objekt gehasht wird. Ich bin mir des Algorithmus und der Parameter nicht sicher, aber meiner Beobachtung nach berechnet er wahrscheinlich einen Hash, der auf allenblobs
undtrees
(ihren Hashes wahrscheinlich) basiertquelle
SHA1("blob" + <size_of_file>
- Gibt es ein zusätzliches Leerzeichen zwischen Blob und Größe? Ist die Größe dezimal? Ist es null vorangestellt?git hash-object
Dies ist eine schnelle Möglichkeit, Ihre Testmethode zu überprüfen:
Ausgabe:
Wo
sha1sum
ist in GNU Coreutils.Dann kommt es darauf an, das Format jedes Objekttyps zu verstehen. Wir haben das Triviale bereits behandelt
blob
, hier sind die anderen:quelle
$(printf "\0$s" | wc -c)
. Beachten Sie das hinzugefügte leere Zeichen. Das heißt, wenn die Zeichenfolge 'abc' mit dem hinzugefügten leeren Zeichen vor sich ist, würde die Länge 4 ergeben, nicht 3. Dann stimmen die Ergebnisse mit sha1sum mit dem Git-Hash-Objekt überein.Basierend auf der Antwort von Leif Gruenwoldt ist hier ein Shell-Funktionsersatz für
git hash-object
:Prüfung:
quelle
Ich brauchte dies für einige Unit-Tests in Python 3, also dachte ich, ich würde es hier lassen.
Ich halte mich
\n
überall an Zeilenenden, aber unter bestimmten Umständen ändert Git möglicherweise auch Ihre Zeilenenden, bevor er diesen Hash berechnet, sodass Sie dort möglicherweise auch eine benötigen.replace('\r\n', '\n')
.quelle