Sind gleichzeitige Git-Pushs immer sicher, wenn der zweite Push nur schnelle Vorläufe vom ersten Push hat?

Lesezeit: 8 Minuten

Sind gleichzeitige Git Pushs immer sicher wenn der zweite Push nur
willkil

Ich möchte Commits im Post-Receive-Hook automatisch von einem zentralen Repo in unserem LAN zu einem anderen zentralen Repo in der Cloud verschieben. Das LAN-Repo wird erstellt mit git clone --mirror git@cloud:/path/to/repo oder gleichwertige Befehle.

Da die übertragenen Dateien im Verhältnis zu unserer Upstream-Bandbreite groß sind, ist es durchaus möglich, dass so etwas passiert:

  1. Alice initiiert einen Push zum LAN-Repo.
  2. Bill zieht aus dem LAN-Repo, während der Post-Receive-Hook läuft.
    • Das LAN-Repo befindet sich mitten im Pushen zum Cloud-Repo.
    • Das bedeutet auch, dass Bills lokales Repo die von Alice gepushten Commits enthält. Durch Tests bestätigt.
  3. Bill initiiert einen Push zum LAN-Repo.
    • Bills Push ist ein schneller Vorlauf von Alices Push, also wird das LAN-Repo ihn akzeptieren.

Wenn der Post-Receive-Hook für das LAN-Repo ausgeführt wird, startet ein zweiter Push vom LAN-Repo zum Cloud-Repo und die beiden werden gleichzeitig ausgeführt.

Ich mache mir keine Sorgen um die Git-Objekte. Das Worst-Case-Szenario ist, dass beide Pushs alle Objekte aus Alices Push hochladen, aber das sollte keine Rolle spielen, soweit ich die Interna von Git verstehe.

Ich mache mir Sorgen um die Schiedsrichter. Nehmen wir an, dass Alice über eine viel langsamere Verbindung gepusht hat, sodass Bills Push zuerst beendet wird. Angenommen, ein Paketverlust oder etwas anderes führt dazu, dass der Push des Hooks vom LAN-Repo zur Cloud von Bills Push beendet wird, bevor der Push des Hooks vom LAN-Repo zur Cloud von Alices Push beendet wird. Wenn sowohl Alice als auch Bill den Master-Branch pushen und Bills Push zuerst beendet wird, was wird die Master-Ref im Cloud-Repo sein? Ich möchte, dass es Bills HEAD ist, da dies der spätere Push ist, aber ich mache mir Sorgen, dass es Alices HEAD sein wird.

Weitere Klarstellung:

Mir ist klar, dass Alices Push von ihrer Maschine zum LAN-Repo fehlschlagen wird, wenn Bills Push von seiner Maschine zum LAN-Repo zuerst beendet wird. In diesem Fall wird der Post-Receive-Hook des LAN-Repos nicht ausgeführt. Nehmen Sie außerdem bitte an, dass niemand Force Pushes durchführen wird Wenn der Post-Receive-Hook auf dem LAN-Repo läuft, werden alle Ref-Änderungen schnell vorgespult.

  • Hinweis: Atomic Pushes werden bald Realität (Git 2.3.1+ Q1/Q2 2015): siehe meine Antwort unten.

    – VonC

    15. Februar 15 um 4:44 Uhr

Wenn Bills Push zuerst beendet wird, schlägt Alices Push fehl, da Git vor der Aktualisierung der Refs sicherstellt, dass die Ref für das Repo immer noch die gleiche ist wie zuvor. In diesem Szenario wird es nicht sein. Am Ende sieht Alice die Fehlermeldung und muss die Probleme lösen. Dasselbe gilt für Bill im umgekehrten Fall. In Ihrem Post-Receive-Hook müssen Sie also sicherstellen, dass die ursprünglichen und neuen Refs für das Repo jetzt unterschiedlich sind. Wenn nicht, pushen Sie überhaupt nicht zum neuen Repo, um etwas Arbeit zu sparen.

Ich sehe jedoch immer noch ein Problem in Ihrem Szenario, und zwar beim Push in die Cloud. Sie können das GLEICHE Problem haben, wenn der Hook zwei gültige Refs an den Cloud-Standort verschiebt. Nur wissen Sie jetzt nicht, ob Sie im Skript zum Repo pushen müssen, wenn es beim ersten Mal fehlschlägt, weil Sie nicht wissen, ob der fehlgeschlagene Ref älter oder neuer als der gepushte war … besonders wenn sie nicht einfach waren schneller Vorlauf, was von Zeit zu Zeit passieren kann. Wenn Sie den Push einfach erzwingen würden, egal was das ist, hätte die Cloud eine ALTE Ref, bis später ein anderer Haken etwas anderes hochschiebt. Im Fall von Alice hätte er die Änderungen von Upstream oder einer beliebigen Anzahl anderer Lösungen zusammengeführt, aber das Skript sollte wahrscheinlich keine solche Entscheidungsfähigkeit haben.

Im Hook können Sie vielleicht etwas Skriptmagie auf das aktuelle Repo anwenden, um Zeitstempel und dergleichen zu bestimmen und nur zu pushen, wenn es einen schnellen Vorlauf gibt, aber das scheint chaotisch zu sein und es ist wahrscheinlicher, dass sowieso eine Zusammenführung erforderlich ist. Ich denke, eine bessere Lösung als die Verwendung eines Post-Receive-Hooks besteht darin, alle fünf Minuten (oder wie oft Sie möchten) einen Cron- oder geplanten Task zu verwenden, der einfach einen Git-Pull auf dem Master-Zweig Ihres Remote-Spiegels ausführt. Wenn Sie keinen Zugriff auf dieses Repo haben, können Sie stattdessen den Force-Push von Ihrem LAN-Repo mit einem Cron-Job durchführen. Ich denke, das ist sicherer als der Haken und weniger kompliziert. Dadurch wird sichergestellt, dass der Zweig in der Backup-Cloud alle paar Minuten immer am richtigen Ort ist und nicht riskiert, einen älteren Ref zu pushen und nie den neuesten zu bekommen, bis ein weiterer Push von einem Benutzer erfolgt, wie es der Hook tut.

  • “In Ihrem Post-Receive-Hook müssen Sie sicherstellen, dass die ursprünglichen und neuen Refs für das Repo jetzt unterschiedlich sind” – ich verstehe nicht, was Sie damit meinen. Wenn der alte und der neue Wert für eine bestimmte Referenz gleich sind, scheint es, dass die Referenz sowieso nicht an den Post-Receive-Hook übergeben wird. Wenn sich keine Refs ändern, wird der Post-Receive-Hook nicht einmal aufgerufen. Ich sehe also keinen Sinn darin, nach dem Unterschied zu suchen.

    – willkil

    8. Dezember ’11 um 17:00 Uhr

  • Eigentlich mache ich mir nur Sorgen um das Problem zwischen dem LAN-Repo und der Cloud, aber ich sehe, dass ich diesen Teil meiner Frage nicht sehr klar formuliert habe und ihn bearbeiten werde.

    – willkil

    8. Dezember 11 um 17:01 Uhr

  • Ich interpretiere Ihre Antwort als Nein, der Push zum Cloud-Repo vom LAN-Repo ist nicht sicher. Ich denke, das Problem ist das git push --mirror (was standardmäßig nach git clone --mirror) Gewalt aktualisiert die Refs.

    – willkil

    8. Dezember 11 um 17:39 Uhr

  • Richtig, der Push in die Cloud aus dem LAN-Repo ist nicht sicher. Ich denke, der Crontab-Job ist die sicherste Option.

    – James

    10. Dezember 11 um 23:06 Uhr

Sind gleichzeitige Git Pushs immer sicher wenn der zweite Push nur
VonC

Git 2.4+ (Q2 2015) wird vorstellen atomare Stöße, was es dem Server erleichtern sollte, die Push-Reihenfolge zu verwalten.
Siehe die Arbeit von Stefan Beller (stefanbeller):

  • ad35eca begehen t5543-atomic-push.sh: Fügen Sie grundlegende Tests für atomare Pushs hinzu

Dies fügt Tests für die atomare Push-Option hinzu.
Die ersten vier Prüfungen Überprüfen Sie, ob die atomare Option unter guten Bedingungen funktioniert und die letzten drei Patches überprüfen, ob die atomare Option verhindert, dass Änderungen gepusht werden, wenn nur eine Referenz nicht aktualisiert werden kann.

  • commit d0e8e09 push.c: ein hinzufügen --atomic Streit

      --[no-]atomic
    

Verwenden Sie eine atomare Transaktion auf der Remote-Seite, falls verfügbar.
Entweder werden alle Refs aktualisiert oder im Fehlerfall werden keine Refs aktualisiert.
Wenn der Server keine atomaren Pushs unterstützt, schlägt der Push fehl.

  • begehen 4ff17f1: send-pack.c: hinzufügen --atomic Kommandozeilenargument

Dies fügt send-pack Unterstützung hinzu, um atomare Pushes auszuhandeln und zu verwenden, wenn der Server dies unterstützt. Atomic Pushes werden durch ein neues Befehlszeilen-Flag aktiviert --atomic.

Dies fügt die atomare Protokolloption hinzu ermöglichen receive-pack um den Client darüber zu informieren, dass er über Atomic-Push-Fähigkeit verfügt.
Mit diesem Commit werden die in den vorherigen Commits eingeführten Funktionen für die Serverseite live geschaltet.
Die Änderungen in der Dokumentation spiegeln die Protokollfunktionen des Servers wider.

   atomic
   ------

Wenn der Server die ‘atomic‘-Fähigkeit ist es in der Lage, atomare Stöße zu akzeptieren.
Wenn der pushende Client diese Fähigkeit anfordert, aktualisiert der Server die Referenzen in einer atomaren Transaktion.
Entweder werden alle Refs aktualisiert oder keine.


Mit Git 2.29 (Q4 2020), “git push(Mann) das atomar sein möchte und ein Push-Zertifikat senden möchte, das gelernt hat, das Push-Zertifikat nicht vorzubereiten und zu signieren, wenn es die lokale Prüfung nicht besteht (daher ist aufgrund der Atomarität bekannt, dass kein Zertifikat benötigt wird).

Sehen a4f324a übergeben (19.09.2020) von Han Xin (chiyutianyi).
(Zusammengeführt von Junio ​​C. Hamano — gitster in b5847b9 übergeben, 25.09.2020)

send-pack: GPG nach Atomic-Push-Prüfung ausführen

Unterzeichnet von: Han Xin

Die Refs-Update-Befehle können auf zwei verschiedene Arten an die Serverseite gesendet werden: GPG-signiert oder unsigniert.
Wir sollten diese beiden Operationen im selben “Endlich, sagen Sie es dem anderen Ende!” Codeblock, aber sie sind durch den Codeblock “Status für jede Referenz löschen” getrennt.
Dies führt zu einem leichten Leistungsverlust, da der fehlgeschlagene atomare Push immer noch unnötige Vorbereitungen für flache Werbe- und GPG-signierte Befehlspuffer durchführt und der Benutzer möglicherweise durch die (mögliche) GPG-Passphrase-Eingabe belästigt werden muss, wenn es nichts zu signieren gibt .

Fügen Sie t5534 einen neuen Testfall hinzu, um sicherzustellen, dass GPG nicht aufgerufen wird, wenn der GPG-signierte atomare Push fehlschlägt.

  • Das ist zwar interessant und ich werde es gerne aktualisieren und verwenden --atomic Wenn es verfügbar ist, mache ich mir keine großen Sorgen mehrere Referenzen in einem einmaliger Druck. Unser Team pusht fast immer nur einen einzigen Schiedsrichter. Ich bin besorgt über das Verhalten von git bzgl mehrere Stöße von a Einzelref. Wenn auf dem Cloud-Server Bills Push von ref/some-branch irgendwie vor Alices Push von ref/some-branch beendet wird, wird der von Alice fehlschlagen? Ich sehe nicht, dass diese Commits dieses Verhalten ändern. Dies impliziert, dass git für die von mir gestellte Single-Ref-Frage bereits sicher ist.

    – willkil

    27. Februar 15 um 20:18 Uhr

  • Und in Bezug auf meinen vorherigen Kommentar nehmen Sie an, dass Bills Referenz/irgendein-Zweig Alices Ref/irgendein-Zweig enthält.

    – willkil

    27. Februar 15 um 20:19 Uhr

.

556630cookie-checkSind gleichzeitige Git-Pushs immer sicher, wenn der zweite Push nur schnelle Vorläufe vom ersten Push hat?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy