Warum verwendet Git Hashes anstelle von Revisionsnummern?

80

Ich habe mich immer gefragt, warum Git Hashes gegenüber Revisionsnummern bevorzugt. Revisionsnummern sind (meiner Meinung nach) viel klarer und leichter zu finden: Es gibt einen Unterschied, wenn Sie jemandem sagen, er solle sich die Revision 1200 ansehen oder 92ba93e festschreiben! (Nur um ein Beispiel zu nennen).

Gibt es einen Grund für diesen Entwurf?

Max Beikirch
quelle
3
Sie können ein Commit mit "v1.0" kennzeichnen und dann auf das Commit mit diesem Tag verweisen. Siehe git-scm.com/book/en/v2/Git-Basics-Tagging
Michael Durrant

Antworten:

114

Eine einzelne, monoton ansteigende Revisionsnummer ist nur für ein zentrales Versionskontrollsystem sinnvoll, bei dem alle Revisionen an einen einzigen Ort fließen, an dem Nummern verfolgt und zugewiesen werden können. Sobald Sie in die DVCS-Welt eintreten, in der zahlreiche Kopien des Repositorys vorhanden sind und Änderungen in willkürlichen Workflows abgerufen und auf sie übertragen werden, trifft das Konzept einfach nicht mehr zu. (Zum Beispiel gibt es keinen Ort, an dem Sie Revisionsnummern zuweisen können. Wenn ich Ihr Repository aufteile und Sie ein Jahr später beschließen, meine Änderungen zu übernehmen, wie kann ein System sicherstellen, dass unsere Revisionsnummern nicht in Konflikt geraten?)

Josh Kelley
quelle
11
Vielleicht möchten Sie sich den Bazaar-Weg ansehen - ein DVCS, das immer noch die Revisionsnummern beibehält. Die einzige Garantie besteht darin, dass die Revisionsnummern innerhalb einer Niederlassung eindeutig sind.
Krlmlr
3
@krlmlr Person 1: "Hey, <P2>, what was revision 12345 for?" P2: "Revision 12345 was commited by <P3>." P3: "I don't have a revision 12345..."- Wenn ich mich richtig erinnere, hat Mercurial ein ähnliches Problem. Wenn sie git verwenden, haben sie alle identische Referenzen für jedes Commit.
Izkata
1
@ Izkata: P1: "Do you have revision with the GUID gdlmsnblngoijlafd-35345-fg?"... Basar hat noch GUIDs ...
krlmlr
5
@ Izkata Mercurial hat kein ähnliches Problem. Sie benutzen Hashes, genau wie git. Sie bieten auch eine lokale Revisionsnummer, um die Eingabe zu vereinfachen.
Hank Gay
1
Bei git sind die ersten 5 Zeichen des Hash häufig eindeutig genug, um eine Kurzform für die vollständige Revisions-ID zu verwenden.
Mendota
40

Sie benötigen Hashes in einem verteilten System. Angenommen, Sie und ein Kollege arbeiten beide am gleichen Repository, und Sie schreiben beide eine Änderung lokal fest und übertragen sie anschließend. Wer erhält die Revisionsnummer 1200 und wer die Revisionsnummer 1201, wenn keine der Parteien Kenntnis voneinander hat? Die einzig realistische technische Lösung besteht darin, einen Hash der Änderungen mit einer bekannten Methode zu erstellen und die Dinge darauf basierend zu verknüpfen.

Interessanterweise unterstützt HG Versionsnummern, diese sind jedoch ausdrücklich nur lokal verfügbar - Ihr Repository verfügt über einen Satz, das Repo Ihres Kollegen verfügt über einen anderen Satz, je nachdem, wie er verschoben und gezogen wird. Dadurch wird die Verwendung der Befehlszeile ein bisschen benutzerfreundlicher als bei Git.

Wyatt Barnett
quelle
34

Datenintegrität.

Ich bin mit den aktuellen Antworten nicht einverstanden. Für ein DVCS sind keine Hashes erforderlich, siehe Bazaar-Methode . Sie können auch mit jeder anderen Art von global eindeutiger Kennung arbeiten. Die Hashes sind eine Maßnahme zur Gewährleistung der Datenintegrität: Sie stellen eine Zusammenfassung der Informationen dar, die in dem Objekt (Festschreiben, Bäume, ...) enthalten sind, auf das der Hash verweist. Es wird angenommen, dass das Ändern des Inhalts ohne Änderung des Hashs (dh eines Vorab-Angriffs oder eines Kollisionsangriffs ) schwierig, wenn auch nicht unmöglich ist. (Wenn Sie wirklich daran interessiert sind, werfen Sie einen Blick auf den Artikel von Marc Stevens aus dem Jahr 2011 ).

Indem Sie mit dem SHA-Hash auf Objekte verweisen, können Sie überprüfen, ob der Inhalt manipuliert wurde. Und da sie (fast) garantiert eindeutig sind, können sie auch als Revisionskennungen verwendet werden - ganz bequem.

Weitere Informationen finden Sie in Kapitel 9 des Git-Buches.

krlmlr
quelle
8
Dies ist keine Sicherheitsmaßnahme, da der Hash für ein geändertes Commit leicht neu berechnet werden kann. Es wird nur für die Integrität verwendet, um den Inhalt mit dem berechneten Hash zu vergleichen - siehe diesen Kommentar von Linus Torvalds zur Verwendung von SHA-1 in Git.
Lee
@Lee: Wenn sich das Repository von Chuck von dem von Alice und Bob in Bezug auf Revisions-Hashes unterscheidet, ist garantiert, dass Chuck auch andere Inhalte hat. Andererseits ist es für Chuck sehr schwierig, ein Repository mit unterschiedlichen Inhalten zu erstellen, die für ihre Revisions-Hashes identisch aussehen.
krlmlr
@Lee: Verpasste deinen Link. Nennen wir es dann "Datenintegrität" ...
krlmlr
sollte die richtige Antwort sein
SuperUberDuper
8

Mit den Worten des Laien:

  • Hashes sollen nahezu universell einzigartig sein. Es wird NICHT garantiert, aber es ist äußerst unwahrscheinlich, dass dieselben SHAs für unterschiedliche Inhalte generiert werden. In der Praxis für ein bestimmtes Projekt können Sie es als einzigartig behandeln.
  • Bei Revisionsnummern müsste ein Namespace verwendet werden, um spezifisch auf Revision 1200 zu verweisen.
  • Git kann sowohl verteilt als auch zentral arbeiten. Wie erhalten Sie die korrekten und eindeutigen Revisionsnummern?
  • Auch die Verwendung von Revisionsnummern würde die falsche Annahme hervorrufen, dass neuere Revisionen höhere Nummern haben sollten, und dies würde aufgrund von Verzweigungen, Zusammenführungen, Neu-Basierungen usw. nicht zutreffen.
  • Sie haben immer die Möglichkeit, Tags zu Commits hinzuzufügen.
Tulains Córdova
quelle
32
Es ist nicht garantiert, dass es einzigartig ist, aber es ist unglaublich wahrscheinlich, dass es einzigartig ist. :)
dsw88
@ mustang2009cobra Das stimmt.
Tulains Córdova
1
Es ist möglich, dass meine Änderung nicht akzeptiert wird, da der Hash unverändert ist. Es ist viel wahrscheinlicher, dass zwei Meteore meinen Computer und den Computer gleichzeitig mit dem Repository angreifen, die Computer zerstören und alle Beteiligten töten.
gnasher729
1

Hash ist nicht die einzige Lösung für verteiltes VCS. Bei einem verteilten System kann jedoch nur die teilweise Anordnung von Ereignissen aufgezeichnet werden. (Für VCS kann das Ereignis ein Commit sein.) Deshalb ist es unmöglich, eine monoton ansteigende Revisionsnummer beizubehalten. Normalerweise verwenden wir so etwas wie eine Vektoruhr (oder einen Vektorzeitstempel), um eine solche teilweise geordnete Beziehung aufzuzeichnen. Dies ist die Lösung, die im Basar verwendet wird .

Aber warum benutzt Git nicht Vector Clock sondern Hash? Ich denke, die Hauptursache ist Kirschbaum . Wenn wir ein Repository mit Cherry Pick bearbeiten, ändert sich die teilweise Reihenfolge der Commits. Die Vektortakte einiger Commits müssen neu zugewiesen werden, um die neue Teilreihenfolge darzustellen. Eine solche Neuzuweisung in einem verteilten System würde jedoch inkonsistente Vektortakte induzieren. Das ist das eigentliche Problem, mit dem sich Hashes befassen.

Che-Sheng Lin
quelle