Ist das halbgeheime leere Baumobjekt von git zuverlässig und warum gibt es keinen symbolischen Namen dafür?
Lesezeit: 10 Minuten
Torek
Git hat einen bekannten, oder zumindest irgendwie bekannten, leeren Baum, dessen SHA1 ist:
4b825dc642cb6eb9a060e54bf8d69288fbee4904
(Sie können dies in jedem Repo sehen, sogar in einem neu erstellten, mit git cat-file -t und git cat-file -p). [Edit made in 2020: the SHA-256 empty tree hash ID is:
as VonC mentions in his answer. My question was apparently about 8 years early. 😀]
Wenn Sie hart arbeiten und sehr vorsichtig sind, können Sie diesen leeren Baum verwenden, um ein Verzeichnis zu speichern, das keine Dateien enthält (siehe Antwort auf Wie füge ich einem Git-Repository ein leeres Verzeichnis hinzu), obwohl dies keine wirklich gute Idee ist.
Es ist nützlicher als ein Argument zu git diff-treewas einer der Sample-Hooks tut.
Was ich mich frage ist,
wie zuverlässig ist das – dh wird eine zukünftige Version von git kein nummeriertes git-Objekt haben? 4b825dc642cb6eb9a060e54bf8d69288fbee4904?
Warum gibt es keinen symbolischen Namen für den leeren Baum (oder gibt es einen?).
(Eine schnelle und schmutzige Möglichkeit, einen symbolischen Namen zu erstellen, besteht darin, den SHA1 einzufügen, z. .git/Nulltree. Leider müssen Sie dies für jedes Repo tun. Es scheint besser zu sein, die magische Zahl einfach in Skripte usw. einzufügen. Ich habe nur eine allgemeine Abneigung gegen magische Zahlen.)
nur um sich an den Hash zu erinnern 😉 use SHA1(“tree 0\0”) = 4b825dc642cb6eb9a060e54bf8d69288fbee4904 (\0 ist NUL-Zeichen)
– Thomas
3. Februar 2016 um 23:20 Uhr
@Thomas: die git hash-object -t tree /dev/null -Methode (aus der Antwort von VonC unten) hat den Vorteil, dass SHA-1 nicht fest codiert ist, falls eine zukünftige Version von Git beispielsweise auf SHA-2 umschaltet. (Ich werde nicht versuchen vorherzusagen, wann das passieren könnte. 🙂 Es wäre einfacher, Mercurial auf SHA-2 umzustellen, da sie dafür Platz gelassen haben.)
– Torek
3. Februar 2016 um 23:53 Uhr
da hast du natürlich recht aber es ist ein gutes stück “nutzloses wissen” und vielleicht hilft es auf jeden fall noch jemandem weiter?!
– Thomas
4. Februar 2016 um 16:40 Uhr
@Thomas: sieht so aus, als ob die Umstellung des Hash-Algorithmus stattfinden könnte früher als erwartet. 🙂
– Torek
26. März 2017 um 4:53 Uhr
In acht nehmen: 6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321 wird bald neu sein 4b825dc642cb6eb9a060e54bf8d69288fbee4904 leerer Baumhasch. Siehe meine bearbeitete Antwort unten.
Daher denke ich, dass es sicherer ist, eine Variable mit dem Ergebnis dieses Befehls als Ihren leeren sha1-Baum zu definieren (anstatt sich auf einen “bekannten Wert” zu verlassen).
Hinweis: Git 2.25.1 (Feb. 2020) schlägt vor begehen 9c8a294:
Als historische Anmerkung ist die Funktion jetzt bekannt als repo_read_object_file() wurde der leere Baum eingelernt 346245a1bb (“Das leere Baumobjekt fest codieren”, 13.02.2008, Git v1.5.5-rc0 — verschmelzen) und die Funktion, die jetzt bekannt ist als oid_object_info() wurde der leere Baum eingelernt c4d9986f5f (“sha1_object_info: untersuchen cached_object store too”, 07.02.2011, Git v1.7.4.1).
Beachten Sie, dass SHA1 auf einigen GitHub-Repositorys auftaucht, wenn der Autor möchte, dass sein erster Commit leer ist (siehe Blogbeitrag „Wie ich meine Git-Repositorys initialisiere“):
$ GIT_AUTHOR_DATE="Thu, 01 Jan 1970 00:00:00 +0000" GIT_COMMITTER_DATE="Thu, 01 Jan 1970 00:00:00 +0000" git commit --allow-empty -m 'Initial commit'
Werde dir geben:
(Siehe den Baum SHA1?)
Du kannst sogar deinen bestehenden Verlauf auf diesen leeren Commit umbasieren (siehe „git: wie fügt man einen Commit als ersten ein und verschiebt alle anderen?“)
In beiden Fällen verlassen Sie sich nicht auf den genauen SHA1-Wert dieses leeren Baums.
Sie folgen einfach a bewährte Methode, Ihr Repo mit einem ersten leeren Commit zu initialisieren.
Dadurch wird ein Commit mit einem SHA1 generiert, der für Ihr Repo, Ihren Benutzernamen, Ihre E-Mail-Adresse und Ihr Erstellungsdatum spezifisch ist (was bedeutet, dass der SHA1 des Commit selbst jedes Mal anders ist).
Aber der Baum, auf den dieser Commit verweist, wird es sein 4b825dc642cb6eb9a060e54bf8d69288fbee4904der leere Baum SHA1.
Seit Git 2.16 (Q1 2018) wird es in einer Struktur verwendet, die nicht mehr (nur) an SHA1 gebunden ist, wie in zu sehen ist eb0ccfd übergeben:
Schalten Sie leere Baum- und Blob-Lookups um, um Hash-Abstraktion zu verwenden
Wechseln Sie die Verwendung von empty_tree_oid und empty_blob_oid die zu verwenden current_hash Abstraktion, die den aktuell verwendeten Hash-Algorithmus darstellt.
Weitere Informationen finden Sie unter „Warum verwendet Git kein moderneres SHA?“: Das ist es SHA-2seit Git 2.19 (Q3 2018)
Mit Git 2.25 (Q1 2020) bereiten sich Tests auf a SHA-2-Übergangund betrifft den leeren Baum.
t/oid-info: Leeren Baum und leere Blob-Werte hinzufügen
Unterzeichnet von: Brian M. Carlson
Die Testsuite wird schließlich lernen, wie sie mit einem anderen Algorithmus als SHA-1 ausgeführt wird. Bereiten Sie sich darauf vor test_oid Funktionsfamilie, wie man die leeren Blob- und leeren Baumwerte nachschlägt, damit sie verwendet werden können.
Der SHA2 “6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321” ist das neue SHA1 “4b825dc642cb6eb9a060e54bf8d69288fbee4904„Leerer Baum.
@torek: Ich habe einige Beispiele rund um die erste Best Practice für leere Commit hinzugefügt, um diesen leeren Baum SHA1 zu veranschaulichen.
– VonC
19. März 2012 um 7:53 Uhr
Nun, eines der Ziele ist es, den Hash des “leeren Baums” als Argument zu verwenden git diff-tree in einigen Skripten, die ich schreibe. Es gibt keine Garantie dafür, dass das Repo einen anfänglich leeren Commit enthält. Ich frage mich also nur, ob diese Skripte eines Tages kaputt gehen könnten.
– Torek
19. März 2012 um 20:57 Uhr
Wenn Sie bestehen -w zu git hash-objecterstellt es das Objekt in dem Repository, für das es ausgeführt wird, und das würde den leeren Baum in dem Repository, für das Sie ausgeführt werden, neu erstellen, falls es in Zukunft jemals verschwinden würde.
– Java-Assistent
3. Januar 2014 um 7:49 Uhr
Wenn Sie vor dem ersten Commit mit rebase vorgehen möchten, können Sie git rebase –root verwenden
– GergelyPolonkai
11. November 2014 um 10:37 Uhr
Oder wenn Sie die Magie von Pfeifen der Magie von Pfeifen vorziehen /dev/null: printf '' | git hash-object --stdin -t tree 🙂
– Ciro Santilli Путлер Капут 六四事
14. Dezember 2014 um 8:17 Uhr
Oleg
Hier ist die Antwort, wie man einen leeren Baum-Commit erstellt, auch wenn das Repository noch nicht leer ist. https://stackoverflow.com/a/14623458/9361507
Aber ich ziehe es vor, dass “leer” ein Tag ist, aber kein Zweig. Einfacher Weg ist:
git tag empty $(git hash-object -t tree /dev/null)
Denn Tag kann ohne Commit direkt auf Tree-ish verweisen. Um nun alle Dateien im Arbeitsbaum zu erhalten:
git diff --name-only empty
Oder das gleiche mit stat:
git diff --stat empty
Alle Dateien als Diff:
git diff empty
Überprüfen Sie Leerzeichen in allen Dateien:
git diff --check empty
…aber die Verwendung der magischen Zahl in Ihrer Tag-Erstellung ist nur, die Frage unter den Teppich zu kehren (nicht mit der magischen Zahl SHA-1)
– Romain Waleri
1. März 2019 um 13:46 Uhr
Nicht wahr. Ich habe Tag verwendet, um auf das baumartige Objekt zu verweisen. Mittlerweile ist dieser Tree-ish durch SHA-1 definiert, in Zukunft kann er beispielsweise auf SHA-256 geändert werden und so weiter (mit Repository-Migration). Aber Tag wird das gleiche sein. 🙂 Das Hauptmerkmal eines Tags ist es, auf das Objekt zu zeigen. Ein Tag kann intern SHA-1 oder etwas anderes verwenden, es handelt sich nur um Git-Interna.
– Oleg
1. März 2019 um 15:41 Uhr
Ich verstehe das. Aber wenn Sie (oder jemand, der dies liest) (oder a Skriptnoch schlimmer) versucht, es (Ihre erste Zeile) zu einem späteren Zeitpunkt anzuwenden, könnte dies bei einem neuen Hash-Algorithmus fehlschlagen, bei dem das Ersetzen Ihrer ersten Zeile durch einen ausgeführten Ausdruck (der diesen Hash erzeugt) weiterhin erfolgreich wäre.
– Romain Waleri
1. März 2019 um 15:49 Uhr
Wenn Sie dies mit einer der Methoden zum automatischen Generieren des leeren Baumhashs kombinieren, können Sie dies zukunftssicher machen (wie @RomainValeri vorschlägt). Wenn es aber nach mir ginge, git rev-parse würde neue Flags oder Schlüsselwörter oder etwas in dieser Richtung haben, um (a) den leeren Baum-Hash und (b) den Null-Commit-Hash zu erzeugen. Beides wäre in Skripten nützlich und würde vor den vorgeschlagenen SHA-256-Änderungen schützen.
– Torek
1. März 2019 um 16:24 Uhr
Okay, geändert. Aber das wird nicht “ein einfachster Weg” sein. 🙂
Wenn es sich aus irgendeinem Grund jemals ändern sollte, können Sie die beiden folgenden Methoden verwenden, um es zu finden. Aber, Ich würde mich ziemlich sicher fühlen, wenn ich den Hash in .bashrc-Aliassen usw. verwenden würde, und ich glaube nicht, dass sich das in absehbarer Zeit ändern wird. Zumindest wäre es wahrscheinlich eine Hauptversion von Git.
Die zwei Wege sind:
Die Antwort oben: git hash-object -t tree --stdin < /dev/null
Einfach ein leeres Repo initiieren und dann ausführen git write-tree in diesem neuen Repo – der Hash wird von git write-tree ausgegeben.
Führen Sie den Befehl mit aus –-stdin gibt mir fatal: Cannot open '–-stdin': No such file or directory mit Git 2.7.2. Läuft aber ohne --stdin wie in der Antwort von VonC gibt den Hash-Wert
– sig
13. Juni 2016 um 10:26 Uhr
Diese Antwort ist nicht sehr nützlich, da der Blog-Post tot ist. Daher stimmen wir diesen Antworten auf SO im Allgemeinen nicht zu.
– Philip Weißhaus
23. August 2017 um 12:57 Uhr
@PhilipWhitehouse, der Blog-Beitrag ist nicht tot, aber auf jeden Fall habe ich die beiden Möglichkeiten in meine Antwort aufgenommen – ich stimme zu, dass es ohne die Einbeziehung dieser beiden Möglichkeiten keine gute Antwort wäre.
– schimm
8. September 2017 um 16:42 Uhr
9863900cookie-checkIst das halbgeheime leere Baumobjekt von git zuverlässig und warum gibt es keinen symbolischen Namen dafür?yes
nur um sich an den Hash zu erinnern 😉 use SHA1(“tree 0\0”) = 4b825dc642cb6eb9a060e54bf8d69288fbee4904 (\0 ist NUL-Zeichen)
– Thomas
3. Februar 2016 um 23:20 Uhr
@Thomas: die
git hash-object -t tree /dev/null
-Methode (aus der Antwort von VonC unten) hat den Vorteil, dass SHA-1 nicht fest codiert ist, falls eine zukünftige Version von Git beispielsweise auf SHA-2 umschaltet. (Ich werde nicht versuchen vorherzusagen, wann das passieren könnte. 🙂 Es wäre einfacher, Mercurial auf SHA-2 umzustellen, da sie dafür Platz gelassen haben.)– Torek
3. Februar 2016 um 23:53 Uhr
da hast du natürlich recht aber es ist ein gutes stück “nutzloses wissen” und vielleicht hilft es auf jeden fall noch jemandem weiter?!
– Thomas
4. Februar 2016 um 16:40 Uhr
@Thomas: sieht so aus, als ob die Umstellung des Hash-Algorithmus stattfinden könnte früher als erwartet. 🙂
– Torek
26. März 2017 um 4:53 Uhr
In acht nehmen:
6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321
wird bald neu sein4b825dc642cb6eb9a060e54bf8d69288fbee4904
leerer Baumhasch. Siehe meine bearbeitete Antwort unten.– VonC
23. Januar 2020 um 8:20 Uhr