Git-Metadaten-Integritätsprüfungen?

635
Wanderer

Ich habe mich heute gefragt, wie gut git die Integrität seiner Metadaten sicherstellt, und ich bin ein bisschen überrascht von dem, was mir begegnet ist. Ich habe die folgenden einfachen Einstellungen zum Testen verwendet:

  • Zwei Arbeitsspeicher, genannt xundy
  • Ein nacktes Repository, genannt xy.git

Also, zunächst xund ydrängen und ziehen x.gitund alles funktioniert gut. Nehmen wir an, eines der Metadaten-Objekte ( .git/objects/...) x.gitwird aus irgendeinem Grund beschädigt (wählen Sie Ihren bevorzugten Zufallsvorfall).

Ich ging eigentlich davon aus, dass beim nächsten Stoß oder Zug etwas zerbrechen würde, aber zu meiner Überraschung schien alles gut zu funktionieren. Mehr Commits, mehr Pushing und Pulling, keine Probleme. Zum ersten Mal wurde berichtet, dass etwas beschädigt war, als ich versuchte, ein anderes funktionierendes Repository aus dem nackten Repository zu klonen, wodurch mein Klon in einem unbrauchbaren Zustand blieb.

Jetzt dachte ich, dass es nicht so schlimm ist, denn dank gits Architektur kann ich im schlimmsten Fall einfach das nackte Repository entleeren und es mit der gesamten Historie aus einem meiner Arbeitssets neu erstellen. Aber nein. Ohne es zu bemerken, hat die beschädigte Datei ihren Weg durch das Einfügen in die aktiven Repositorys gefunden, sodass es unmöglich ist, auch ein neues, nacktes Repository aus ihnen zu klonen.

Dies passiert nicht nur, wenn ich mit einer beschädigten Datei im bloßen Repository beginne. Es ist auch möglich, eine beschädigte Datei aus einem funktionierenden Repository auf diese Weise in ein bloßes Repository einzufügen.

Sicher, man kann das auf andere Weise beheben, aber ich bin immer noch überrascht (und ein bisschen besorgt), wie einfach es ist, das Repository für alle, die damit arbeiten, durcheinander zu bringen. Zumal der Fehler unbemerkt bleiben kann, bis das nächste Mal versucht wird, zu klonen. Sollte es nicht irgendwo Überprüfungen geben?

Wer ist hier bereit zu versuchen, ob es reproduzierbar ist? Ich habe mit git Version 2.7.4 experimentiert.

Alle Hinweise, wie Sie gegen Korruption vorgehen können, sind sehr willkommen.

1

1 Antwort auf die Frage

1
grawity

Ich ging eigentlich davon aus, dass beim nächsten Stoß oder Zug etwas zerbrechen würde, aber zu meiner Überraschung schien alles gut zu funktionieren. Mehr Commits, mehr Pushing und Pulling, keine Probleme.

Jedes Objekt - Datei, Festschreibung usw. - ist nach dem SHA1-Hash seines Inhalts (plus einem kleinen Header) benannt. Wenn ein einzelnes Objekt zur Verwendung in den Speicher eingelesen wird, werden die Daten gehasht und mit dem Namen des Objekts verglichen. Bei einer Nichtübereinstimmung wird ein Fehler angezeigt.

Die meisten Vorgänge müssen jedoch nicht das gesamte Repository in den Speicher lesen. Im Allgemeinen lesen alle Befehle nur das Nötigste erforderlich - natürlich, Sie würden das Problem bemerkt haben, wenn Sie einen gegen sie begehen oder diff gebrochen zu überprüfen versucht, aber solche Operationen wie die Schaffung eines nicht überhaupt über frühere Objekte begehen kümmern. Selbst das Pushing erfordert nur eine kleine Auswahl von Objekten (als Delta-Basis für "dünne" Pakete), da beide Peers wissen, was die andere Seite bereits hat.

(Diese Optimierung ist ein direktes Ergebnis des Snapshot-basierten Layouts. Zum Beispiel muss git add kein Delta gegen die alten Dateien ausführen, da es einfach einen neuen Snapshot aufbaut, während es weitergeht. Dann konvertiert git commit diesen Snapshot in ein Commit / Baumobjekte, ohne etwas über das vorherige Commit mit Ausnahme der ID zu wissen .)

Dies passiert nicht nur, wenn ich mit einer beschädigten Datei im bloßen Repository beginne. Es ist auch möglich, eine beschädigte Datei aus einem funktionierenden Repository auf diese Weise in ein bloßes Repository einzufügen.

Denken Sie zunächst daran, dass ein Klone desselben Computers und desselben Dateisystems keine Objekte packt und überträgt - er verbindet lediglich die Dateien, um Platz und Zeit zu sparen. Sie müssen dies explizit deaktivieren, indem Sie file://statt eines einfachen Pfads von einer URL klonen .

Ein Klon über SSH oder HTTPS (oder die oben genannten file: // URLs) liest und schreibt jedoch die Objektdaten, um das Transfer Pack aufzubauen, sodass ein beschädigtes Objekt, das Teil der Übertragung sein sollte, das Programm abbricht verarbeiten.

Wenn Sie es irgendwie schaffen, ein beschädigtes Objekt auf einen Remote- Server zu verschieben, da es sowohl durch das lokale Packen als auch durch das Remote-Auspacken gleitet, ist das etwas ungewöhnlich (vor allem nach der 2013er Geschichte von git.kde.org ), und ich würde diese Bedenken äußern auf der Git-Mailingliste.

(Machen Sie sich keine Sorgen, dass in der Dokumentation transfer.fsckObjectsstandardmäßig von der Deaktivierung die Rede ist. Sie deaktiviert nur die Überprüfung der Objektstruktur und -syntax, nicht die Hash-Überprüfung.)

Sollte es nicht irgendwo Überprüfungen geben?

Eine vollständige Überprüfung kann manuell mit dem git fsckBefehl durchgeführt werden. Es ist eine gute Idee, es in Ihren zentralen Repositories zu erstellen. Die vollständige Prüfung ist nicht automatisiert, da es eine unzumutbare Zeit dauern würde, um das vollständige Repository bei jedem Festschreiben / Push / Pull / was für alle außer den kleinsten Git-Repositorys erneut zu überprüfen.

Eine Teilprüfung erfolgt implizit, wenn git den git gc --autoHintergrundwartungsprozess durchführt. Diese Wartung liest alle kürzlich erstellten "losen" Objekte und archiviert sie in einer .pack-Datei, sodass die Überprüfung dieser Objekte kostenlos erfolgt. (Sie werden jedoch nicht nach einem voreingestellten Zeitplan ausgeführt, sondern immer dann, wenn Sie mehr lose Objekte als das festgelegte Limit haben.)