Gits Dokumentation für den rebase
Befehl ist ziemlich kurz:
--preserve-merges
Instead of ignoring merges, try to recreate them.
This uses the --interactive machinery internally, but combining it
with the --interactive option explicitly is generally not a good idea
unless you know what you are doing (see BUGS below).
Was passiert also eigentlich, wenn Sie verwenden --preserve-merges
? Wie unterscheidet es sich vom Standardverhalten (ohne dieses Flag)? Was bedeutet es, eine Zusammenführung usw. "neu zu erstellen"?
git
git-rebase
Chris
quelle
quelle
git --rebase-merges
wird letztendlich das alte ersetztgit --preserve-merges
. Siehe meine Antwort untenAntworten:
Wie bei einer normalen Git-Rebase
--preserve-merges
identifiziert Git mit zuerst eine Liste von Commits, die in einem Teil des Commit-Diagramms vorgenommen wurden, und spielt diese Commits dann über einem anderen Teil ab. Die Unterschiede--preserve-merges
betreffen, welche Commits für die Wiedergabe ausgewählt werden und wie diese Wiedergabe für Zusammenführungs-Commits funktioniert.Um die Hauptunterschiede zwischen normaler und zusammenführungserhaltender Rebase genauer zu erläutern:
git checkout <desired first parent>
), während sich die normale Rebase darüber keine Gedanken machen muss.Zuerst werde ich versuchen, "ausreichend genau" zu beschreiben, was Rebase
--preserve-merges
tut, und dann wird es einige Beispiele geben. Man kann natürlich mit den Beispielen beginnen, wenn das sinnvoller erscheint.Der Algorithmus in "Brief"
Wenn Sie wirklich in das Unkraut eindringen möchten, laden Sie die Git-Quelle herunter und erkunden Sie die Datei
git-rebase--interactive.sh
. (Rebase ist nicht Teil des C-Kerns von Git, sondern in Bash geschrieben. Und hinter den Kulissen teilt es Code mit "Interactive Rebase".)Aber hier werde ich skizzieren, was ich für das Wesentliche halte. Um die Anzahl der Dinge zu verringern, über die man nachdenken muss, habe ich mir ein paar Freiheiten genommen. (zB versuche ich nicht, die genaue Reihenfolge, in der die Berechnungen stattfinden, mit 100% iger Genauigkeit zu erfassen, und ignoriere einige weniger zentral erscheinende Themen, z. B. was mit Commits zu tun ist, die bereits zwischen Zweigen ausgewählt wurden).
Beachten Sie zunächst, dass eine nicht zusammenführungserhaltende Rebase ziemlich einfach ist. Es ist mehr oder weniger:
Rebase
--preserve-merges
ist vergleichsweise kompliziert. Hier ist so einfach, wie ich es geschafft habe, ohne Dinge zu verlieren, die ziemlich wichtig erscheinen:Rebase mit einem
--onto C
Argument sollte sehr ähnlich sein. Anstatt die Festschreibungswiedergabe am KOPF von B zu starten, starten Sie stattdessen die Festschreibungswiedergabe am KOPF von C. (Und verwenden Sie C_new anstelle von B_new.)Beispiel 1
Nehmen Sie zum Beispiel ein Commit-Diagramm
m ist eine Zusammenführung mit den Eltern E und G.
Angenommen, wir haben das Thema (H) über Master (C) mit einer normalen, nicht zusammenführungserhaltenden Rebase neu basiert. (Beispiel: Checkout-Thema; Rebase-Master .) In diesem Fall würde git die folgenden Commits für die Wiedergabe auswählen:
und aktualisieren Sie dann das Festschreibungsdiagramm wie folgt:
(D 'ist das wiedergegebene Äquivalent von D usw.)
Beachten Sie, dass Merge Commit m nicht für die Wiedergabe ausgewählt ist.
Wenn wir stattdessen eine
--preserve-merges
Rebase von H über C durchführen würden (z. B. Checkout-Thema; Rebase --preserve-merges master ). In diesem neuen Fall würde git die folgenden Commits für die Wiedergabe auswählen:Jetzt m wurde für die Wiedergabe ausgewählt. Beachten Sie auch, dass die Zusammenführungseltern E und G vor dem Zusammenführungs-Commit m zur Aufnahme ausgewählt wurden.
Hier ist das resultierende Commit-Diagramm:
Wieder ist D 'eine von Kirschen gepflückte (dh neu erstellte) Version von D. Gleiches gilt für E' usw. Jedes Commit, das nicht auf dem Master ausgeführt wurde, wurde wiederholt. Sowohl E als auch G (die zusammengeführten Eltern von m) wurden als E 'und G' neu erstellt, um als Eltern von m 'zu dienen (nach dem Rebase bleibt die Baumhistorie immer noch dieselbe).
Beispiel 2
Anders als bei einer normalen Rebase kann eine zusammenführungserhaltende Rebase mehrere untergeordnete Elemente des Upstream-Kopfes erstellen.
Betrachten Sie zum Beispiel:
Wenn wir H (Thema) über C (Master) neu gründen, werden folgende Commits für die Basis neu ausgewählt:
Und das Ergebnis ist wie folgt:
Beispiel 3
In den obigen Beispielen sind sowohl das Zusammenführungs-Commit als auch seine beiden übergeordneten Elemente wiedergegebene Commits und nicht die ursprünglichen Eltern, die das ursprüngliche Zusammenführungs-Commit hat. Bei anderen Rebases kann ein wiedergegebenes Zusammenführungs-Commit jedoch zu Eltern führen, die sich vor dem Zusammenführen bereits im Commit-Diagramm befanden.
Betrachten Sie zum Beispiel:
Wenn wir das Thema auf den Master zurücksetzen (Zusammenführungen beibehalten), werden die Commits für die Wiedergabe ausgeführt
Das neu geschriebene Commit-Diagramm sieht folgendermaßen aus:
Hier erhält das wiedergegebene Zusammenführungs-Commit m 'Eltern, die im Commit-Diagramm bereits vorhanden waren, nämlich D (der KOPF des Masters) und E (eines der Eltern des ursprünglichen Merge-Commits m).
Beispiel 4
Die Zusammenführung, bei der die Zusammenführung erhalten bleibt, kann in bestimmten Fällen "leeres Festschreiben" verwirrt werden. Zumindest trifft dies nur auf einige ältere Versionen von git zu (zB 1.7.8.)
Nehmen Sie dieses Commit-Diagramm:
Beachten Sie, dass sowohl Commit m1 als auch m2 alle Änderungen von B und F enthalten sollten.
Wenn wir versuchen,
git rebase --preserve-merges
H (Thema) auf D (Master) zu übertragen, werden die folgenden Commits für die Wiedergabe ausgewählt:Beachten Sie, dass die in m1 vereinigten Änderungen (B, F) bereits in D enthalten sein sollten. (Diese Änderungen sollten bereits in m2 integriert sein, da m2 die untergeordneten Elemente von B und F zusammenführt.) D sollte wahrscheinlich entweder ein No-Op sein oder ein leeres Commit erstellen (dh eines, bei dem der Unterschied zwischen aufeinanderfolgenden Revisionen leer ist).
Stattdessen kann git jedoch den Versuch ablehnen, m1 über D wiederzugeben. Sie können folgende Fehlermeldung erhalten:
Es sieht so aus, als hätte man vergessen, ein Flag an git zu übergeben, aber das zugrunde liegende Problem ist, dass git es nicht mag, leere Commits zu erstellen.
quelle
git rebase --preserve-merges
das viel langsamer ist alsrebase
ohne--preserve-merges
. Ist das ein Nebeneffekt beim Finden der richtigen Commits? Kann man etwas tun, um es zu beschleunigen? (Übrigens ... danke für die sehr detaillierte Antwort!)Git 2.18 (Q2 2018) wird die
--preserve-merge
Option durch Hinzufügen einer neuen Option erheblich verbessern ."
git rebase
" gelernt "--rebase-merges
", die gesamte Topologie des Commit-Graphen an eine andere Stelle zu übertragen .(Hinweis: Git 2.22, Q2 2019, ist tatsächlich veraltet
--preserve-merge
, und Git 2.25, Q1 2020, macht keine Werbung mehr in der "git rebase --help
" Ausgabe. )Sehen Sie verpflichten 25cff9f , begehen 7543f6f , begehen 1131ec9 , begehen 7ccdf65 , begehen 537e7d6 , begehen a9be29c , begehen 8f6aed7 , begehen 1644c73 , begehen d1e8b01 , begehen 4c68e7d , begehen 9055e40 , begehen cb5206e , begehen a01c2a5 , begehen 2f6b1d1 , begehen bf5c057 (25. April 2018) von Johannes Schindelin (
dscho
) .Siehe Commit f431d73 (25. April 2018) von Stefan Beller (
stefanbeller
) .Siehe Commit 2429335 (25. April 2018) von Phillip Wood (
phillipwood
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 2c18e6a , 23. Mai 2018)git rebase
Die Manpage enthält jetzt einen vollständigen Abschnitt, der sich der Neugestaltung des Verlaufs durch Zusammenführungen widmet .Extrakt:
Siehe 1644c73 verpflichten für ein kleines Beispiel:
Was ist der Unterschied zu
--preserve-merge
?Commit 8f6aed7 erklärt:
Und mit "Mit freundlichen Grüßen" bezieht sich der Autor auf sich selbst: Johannes Schindelin (
dscho
) , der der Hauptgrund (mit einigen anderen Helden - Hannes, Steffen, Sebastian, ...) ist, dass wir Git For Windows haben (obwohl damals - 2009 - war das nicht einfach ).Er arbeitet seit September 2015 bei Microsoft. Dies ist sinnvoll, da Microsoft Git jetzt stark nutzt und seine Dienste benötigt.
Dieser Trend begann 2013 mit TFS . Seitdem verwaltet Microsoft das größte Git-Repository der Welt ! Und, seit Oktober 2018 hat Microsoft GitHub übernommen .
Sie können Johannes in diesem Video sprechen sehen für Git Merge 2018 im April 2018 .
Hier spricht Jonathan über Andreas Schwab von Suse.
Sie können einige ihrer Diskussionen im Jahr 2012 sehen .
(Auf das Git Garden Shears-Skript wird in diesem Patch in Commit 9055e40 verwiesen. )
Git 2.19 (Q3 2018) verbessert die neue
--rebase-merges
Option, indem sie funktioniert--exec
.Die
--exec
Option " " to "git rebase --rebase-merges
" platzierte die exec-Befehle an falschen Stellen, was korrigiert wurde.Siehe Commit 1ace63b (09. August 2018) und Commit f0880f7 (06. August 2018) von Johannes Schindelin (
dscho
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 750eb11 , 20. August 2018)Git 2.22 (Q2 2019) korrigiert die Verwendung von refs / rewritten / hierarchy zum Speichern von Rebase-Zwischenzuständen, wodurch die Hierarchie von Natur aus pro Arbeitsbaum erstellt wird.
Siehe Commit b9317d5 , Commit 90d31ff , Commit 09e6564 (07. März 2019) von Nguyễn Thái Ngọc Duy (
pclouds
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 917f2cd , 9. April 2019)a9be29c (Sequenzer: Refs
label
erstellen, die mit dem Befehl worktree-local, 2018-04-25, Git 2.19 generiert wurden) wirdrefs/rewritten/
als Referenzraum pro Arbeitsbaum hinzugefügt.Leider (mein schlechtes) gibt es einige Stellen, die aktualisiert werden müssen, um sicherzustellen, dass es wirklich pro Arbeitsbaum ist.
Mit Git 2.24 (Q4 2019) lernte "
git rebase --rebase-merges
", verschiedene Zusammenführungsstrategien voranzutreiben und strategiespezifische Optionen an sie weiterzugeben.Siehe Commit 476998d (04. September 2019) von Elijah Newren (
newren
) .Siehe e1fac53 begehen , begehen a63f990 , begehen 5dcdd74 , begehen e145d99 , begehen 4e6023b , begehen f67336d , begehen a9c7107 , begehen b8c6f24 , begehen d51b771 , begehen c248d32 , begehen 8c1e240 , begehen 5efed0e , begehen 68b54f6 , begehen 2e7bbac , begehen 6180b20 , begehen d5b581f (31 Jul 2019) vonJohannes Schindelin (
dscho
).(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 917a319 , 18. September 2019)Mit Git 2.25 (Q1 2020) ist die Logik, die verwendet wird, um die lokalen und globalen Refs des Arbeitsbaums voneinander zu unterscheiden, festgelegt, um die Zusammenführung zu erleichtern.
Siehe Commit f45f88b , Commit c72fc40 , Commit 8a64881 , Commit 7cb8c92 , Commit e536b1f (21. Oktober 2019) von SZEDER Gábor (
szeder
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit db806d7 , 10. November 2019)quelle
--preserve-merges
"bewahrt" die Zusammenführungen nicht so, wie Sie es möchten, es ist sehr naiv. Auf diese Weise können Sie die Zusammenführungs-Commits und die übergeordneten Commit-Beziehungen beibehalten und gleichzeitig die Flexibilität einer interaktiven Rebase erhalten. Diese neue Funktion ist fantastisch und ohne diese gut geschriebene SO-Antwort hätte ich es nicht gewusst!