wake-up-neo.com

git Push --force-with-lease vs. --force

Ich versuche den Unterschied zwischen zu verstehen

git Push -f

und

git Push --force-with-lease

meine Vermutung ist, dass letztere nur auf die Fernbedienung pusht wenn die Fernbedienung keine Commits hat, die die lokale Verzweigung nicht hat?

Wenn es einen besseren Weg gibt, die Frage zu formulieren, lmk, aber hoffentlich ist es klar.

52
Alexander Mills

force überschreibt einen entfernten Zweig mit Ihrem lokalen Zweig.

--force-with-lease ist eine sicherere Option, die keine Arbeit in der Remote-Verzweigung überschreibt, wenn der Remote-Verzweigung mehr Commits hinzugefügt wurden (von einem anderen Teammitglied oder Kollegen oder von Ihnen). Es stellt sicher, dass Sie niemanden überschreiben, der mit Gewalt drückt.

Ich denke, Ihre allgemeine Vorstellung, die den Befehl umgibt, ist richtig. Wenn der Remote-Zweig den gleichen Wert wie der Remote-Zweig auf Ihrem lokalen Computer hat, werden Sie Remote überschreiben. Wenn es nicht denselben Wert hat, weist dies auf eine Änderung hin, die eine andere Person an der Remote-Verzweigung vorgenommen hat, während Sie an Ihrem Code gearbeitet haben, und überschreibt daher keinen Code. Wenn in remote zusätzliche Commits vorhanden sind, stimmen die Werte offensichtlich nicht überein.

Ich denke nur an --force-with-lease als Option, wenn ich sicherstellen möchte, dass kein Teamkollegen-Code überschrieben wird. Viele Teams in meiner Firma verwenden --force-with-lease als Standardoption für einen Fail-Safe. Dies ist in den meisten Fällen unnötig, erspart Ihnen jedoch viele Kopfschmerzen, wenn Sie etwas überschreiben, das eine andere Person zur Fernsteuerung beigetragen hat.

Ich bin mir sicher, dass Sie sich die Dokumentation angesehen haben, aber hier finden Sie möglicherweise eine ausführlichere Erklärung:

https://git-scm.com/docs/git-Push

27
chevybow

git Push --force ist destruktiv, da es das entfernte Repository bedingungslos mit dem lokalen Repository überschreibt. Von gits Push --force wird dringend abgeraten, da es andere Commits zerstören kann, die bereits in ein freigegebenes Repository verschoben wurden. Eine der häufigsten Ursachen für Force Pushs ist, wenn wir gezwungen sind, einen Zweig neu zu gründen.

Zum Beispiel. Wir haben ein Projekt mit einem Feature-Zweig, an dem sowohl Alice als auch Bob arbeiten werden. Beide klonen dieses Repository und beginnen mit der Arbeit. Alice vervollständigt zunächst ihren Teil der Funktion und überträgt diese an das Haupt-Repository. Das ist alles schön und gut. Bob beendet auch seine Arbeit, aber bevor er sie hochdrückt, bemerkt er, dass einige Änderungen in master zusammengeführt wurden. Um einen sauberen Baum zu behalten, führt er einen Rebase gegen den Master-Zweig durch. Wenn er diesen rebasierten Zweig pusht, wird er natürlich abgelehnt. Da er jedoch nicht merkt, dass Alice ihre Arbeit bereits vorangetrieben hat, führt er eine Push - Force durch. Leider werden dadurch alle Aufzeichnungen über Alice 'Änderungen im zentralen Repository gelöscht.

Was - force-with-lease bewirkt, ist die Ablehnung der Aktualisierung eines Zweigs, es sei denn, dies ist der erwartete Zustand. niemand hat den Zweig stromaufwärts aktualisiert. In der Praxis funktioniert dies, indem überprüft wird, ob der vorgelagerte Ref das ist, was wir erwarten, da Refs Hashes sind und die Kette der Eltern implizit in ihren Wert codieren.

Hier ist ein guter Beitrag zu git Push --force und git Push --force-with-lease.

14
Shakil

Auf der Suche nach einer Antwort aus glaubwürdigen und/oder offiziellen Quellen.

Das von torek in den Kommentaren und in seiner anderen Antwort erwähnte "Vergleichen und Tauschen" wird durch Git-Quellen) noch weiter verdorben selbst .

letzterer drückt nur auf die Fernbedienung, wenn die Fernbedienung keine Commits hat, die die lokale Zweigstelle nicht hat?

Diese Funktion wurde eingeführt in commit 28f5d17 (Dez. 2013, Git v1.8.5-rc0)

--force-with-lease schützt alle Remote-Referenzen, die aktualisiert werden sollen, indem der aktuelle Wert mit einem angemessenen Standardwert übereinstimmt, sofern nicht anders angegeben.

Im Moment ist "einige vernünftige Standardeinstellungen" vorläufig definiert als " der Wert des Fernverfolgungszweigs, den wir für die Referenz der zu aktualisierenden Fernbedienung haben ". , und es ist ein Fehler, wenn wir keinen solchen Remote-Tracking-Zweig haben.

"Leasing" bedeutet also:

"force-with-lease ": Sie gehen davon aus, dass Sie den Lease für den Ref übernommen haben, als Sie entschieden haben, wie der neu basierende Verlauf lauten soll, und Sie können nur zurückschieben, wenn der Lease nicht gebrochen wurde.

Die Quellen erwähnen immer noch "cas":

  • Diese Option hieß ursprünglich "cas" (für "Compare and Swap"), der Name, den niemand mochte, weil er zu technisch war .
  • Der zweite Versuch nannte es "lockref" (weil es konzeptionell dem Drücken nach dem Nehmen einer Sperre gleicht), aber das Wort "Sperre" wurde gehasst, weil es implizierte, dass Push von anderen abgelehnt werden könnte, was bei dieser Option nicht der Fall ist.
  • Diese Runde nennt es "Force-with-Lease".
    Sie gehen davon aus, dass Sie den Lease für den Schiedsrichter abgeschlossen haben, als Sie entschieden haben, wie der neu basierende Verlauf lauten soll, und Sie können nur zurückschieben, wenn der Lease nicht gebrochen wurde.

Damit: "git Push --force-with-lease vs. --force "

Wie ich in " Push --force-with-lease standardmäßig ", wie Git 2.13 (Q2 2017) erwähnt, dass die Option --force-with-lease kann ignoriert werden wenn ein Hintergrundprozess (wie in einem IDE mit einem Git-Plugin) ausgeführt wird git fetch Origin.
In diesem Fall, --force setzt sich durch.

13
VonC

Angenommen, alle Pre-Receive-Hooks auf dem Server akzeptieren den Push, ist dies immer erfolgreich:

git Push --force

Dabei wird eine spezifische clientseitige Überprüfung durchgeführt, bevor fortgefahren wird:

git Push --force-with-lease

Sie können die spezifische Prüfung manuell durchführen. Hier ist der "Lease-Checking" -Algorithmus:

  1. Finden Sie Ihren aktuellen Zweig heraus.

  2. Führen Sie git for-each-ref refs/remotes Aus. Notieren Sie sich die Commit-ID, die Ihrer Meinung nach dem Upstream-Status Ihrer aktuellen Filiale entspricht.

Wenn Sie sich beispielsweise in der Verzweigung "foo" befinden, notieren Sie sich die mit "refs/remotes/Origin/foo" verknüpfte Festschreibungs-ID.

  1. Ermitteln Sie jetzt die tatsächliche Festschreibungs-ID des Remote-Zweigs auf dem Upstream-Git-Server.

  2. Lassen Sie "git Push" nur dann fortfahren, wenn die aus Schritt 2 und Schritt 3 extrahierten Commit-IDs übereinstimmen. Fahren Sie mit anderen Worten nur fort, wenn die Vorstellung Ihres lokalen Git-Klons von Upstream mit der tatsächlichen von Upstream übereinstimmt.

Hier gibt es eine traurige Implikation: Da git fetch Alle Referenzen unter "refs/remotes/Origin/*" auf ihre neuesten Versionen aktualisiert, ist diese Befehlskombination im Wesentlichen identisch mit git Push --force:

git fetch

# The command below behaves identically to "git Push --force"
# if a "git fetch" just happened!

git Push --force-with-lease

Um diese inhärente Schwäche von git Push --force-with-lease Zu umgehen, versuche ich, niemals git fetch Auszuführen. Stattdessen führe ich immer git pull --rebase Aus, wenn ich eine Synchronisierung mit dem Upstream durchführen muss, da git pull Nur eine einzige Referenz unter refs/remotes aktualisiert, wodurch die "Lease" von --force-with-lease Nützlich bleibt.

4

Force-with-Lease ist nicht unbedingt sicher. Es funktioniert einfach so, wie Sylvie es gesagt hat. Eine Anmerkung: In Git ist ein Zweig nur ein Zeiger auf ein Commit. Und Commits zeigen auf null oder mehr übergeordnete Commits. Selbst wenn Sie den Zweig mit einem Hard-Git-Reset und einem erzwungenen Push oder einem Push mit - - Force-with-Lease geändert haben, ohne es zu wollen, ist das nicht unbedingt ein großes Problem. Sie können Ihr lokales Git-Reflog verwenden, um zu sehen, wie sich Ihr lokaler Tipp auf den Zweigen (Wo war HEAD zu diesem Zeitpunkt?)) Geändert hat, und den Zweig zurücksetzen und erneut pushen. Dann verlieren Sie nur neue Commits auf dem Remote-Zweig, aber auch sie könnten von den Teammitgliedern wiederhergestellt werden.

1
Fish