Mit Git 2.30 (Q1 2021) wird es eine neu Fusionsstrategie: ORT (" Angeblich rekursiver Zwilling ").
git merge -s ort
Dies kommt von dieses Thema von Elijah Newren:
Im Moment nenne ich es "Ostensibly Recursive's Twin" oder kurz "ort". > Zunächst sollten die Leute keinen Unterschied zwischen ihr und der aktuellen rekursiven Strategie feststellen können, außer der Tatsache, dass ich denke, dass ich sie ein wenig schneller machen kann (besonders für große Repos).
Aber es sollte mir erlauben, einige (zugegebenermaßen Eckfälle) Bugs zu beheben, die im aktuellen Design schwieriger zu handhaben sind, und ich denke, dass ein Merge, der nicht die $GIT_WORK_TREE
o $GIT_INDEX_FILE
wird einige interessante neue Funktionen ermöglichen.
Das ist jedenfalls die Hoffnung.
Problem :
In einer idealen Welt sollten wir das tun:
-
fragen Sie unpack_trees()
zu tun " read-tree -m
" ohne " -u
";
-
alle merge-rekursiven Berechnungen im Kern durchführen und den und bereiten den daraus resultierenden Index vor, während der aktuelle Index intakt bleibt;
-
den aktuellen In-Core-Index und den sich daraus ergebenden In-Core-Index vergleichen und feststellen, welche Pfade im Arbeitsbaum hinzugefügt, aktualisiert oder entfernt werden müssen, und sicherstellen, dass keine Informationen verloren gehen, wenn die Änderung in den Arbeitsbaum übernommen wird;
Z.B. will das Ergebnis eine Datei erstellen, in der der Arbeitsbaum ein Verzeichnis mit nicht erweiterbarem Inhalt enthält, das Ergebnis will eine Datei entfernen, in der der Arbeitsbaum eine lokale Änderung aufweist, usw.;
Und dann schließlich
-
die Aktualisierung des Arbeitsbaums durchführen, damit er so aussieht, wie es der resultierende In-Core-Index vorgibt.
Ergebnis:
Ver Commit 14c4586 (02 Nov 2020), fe1a21d übergeben (29. Oktober 2020), und 47b1e89 festlegen , 17e5574 festlegen (27. Oktober 2020) von Elijah Newren ( newren
) .
(Zusammengefasst von Junio C. Hamano -- gitster
-- in a1f9595 übertragen , 18. November 2020)
merge-ort
Barebones API der neuen Merge-Strategie mit leerer Implementierung
Abgezeichnet von: Elijah Newren
Dies ist der Beginn einer neuen Fusionsstrategie.
Obwohl es einige API-Unterschiede gibt und die Implementierung einige Unterschiede im Verhalten aufweist, ist sie im Wesentlichen als möglicher Ersatz für merge-recursive.c
.
Es wird jedoch parallel zu merge-recursive entwickelt, so dass wir genügend Zeit haben, um herauszufinden, wie sich diese Unterschiede in der realen Welt auswirken, während die Leute immer noch auf merge-recursive zurückgreifen können.
(Außerdem möchte ich vermeiden, merge-recursive während dieses Prozesses zu ändern, um es stabil zu halten).
Der Hauptunterschied besteht darin, dass die Aktualisierung des Arbeitsbaums und des Index nicht gleichzeitig mit dem Zusammenführungsalgorithmus erfolgt, sondern ein separater Nachbearbeitungsschritt ist.
Die neue API ist so konzipiert, dass man wiederholte Zusammenführungen durchführen kann (z.B. während eines Rebase oder Cherry-Pick) und den Index und den Arbeitsbaum am Ende nur einmal aktualisiert, anstatt ihn mit jedem Zwischenergebnis zu aktualisieren.
Außerdem kann man eine Zusammenführung zwischen zwei Zweigen durchführen, die weder mit dem Index noch mit dem Arbeitsbaum übereinstimmen, ohne den Index oder den Arbeitsbaum zu zerstören.
Und:
Ver Commit 848a856 , Übergabe fd15863 , 23bef2e übergeben , c8c35f6 übergeben , c12d1f2 übergeben , 727c75b übertragen , 489c85f übergeben , ef52778 übertragen , Übergabe f06481f (26. Oktober 2020) von Elijah Newren ( newren
) .
(Zusammengefasst von Junio C. Hamano -- gitster
-- in 66c62ea festlegen , 18. November 2020)
t6423, t6436
Hinweis: Verbesserte ort-Behandlung bei unsauberen Dateien
Abgezeichnet von: Elijah Newren
Das "rekursive" Backend stützt sich auf unpack_trees()
um zu prüfen, ob nicht zusammengefasste Änderungen durch eine Zusammenführung überschrieben würden, aber unpack_trees()
versteht keine Umbenennungen - und wenn es zurückkehrt, hat es bereits viele Aktualisierungen in den Arbeitsbaum und den Index geschrieben.
Daher musste "recursive" einen speziellen 4-Wege-Merge durchführen, bei dem es auch die Arbeitskopie als zusätzliche Quelle von Unterschieden behandeln musste, die wir sorgfältig vermeiden mussten, zu überschreiben, was dazu führte, dass Dateien an neue Orte verschoben wurden, um Konflikte zu vermeiden.
Das "ort"-Backend hingegen führt die komplette Zusammenführung im Speicher durch und aktualisiert den Index und die Arbeitskopie erst im Nachgang .
Wenn schmutzige Dateien im Weg sind, kann das Programm die Zusammenführung einfach abbrechen.
t6423
Verbesserte Kennzeichnung von Konfliktmarkierungen im Ort-Backend erwarten
Abgezeichnet von: Elijah Newren
Konfliktmarkierungen tragen einen zusätzlichen Vermerk der Form REF-OR-COMMIT:DATEINAME um zu unterscheiden, woher der Inhalt stammt, wobei die :FILENAME
Stück weggelassen wird, wenn es für beide Seiten der Geschichte gleich ist (so tragen nur Umbenennungen mit inhaltlichen Konflikten diesen Teil der Anmerkung).
Es gab jedoch Fälle, in denen die :FILENAME
wurde versehentlich ausgelassen, weil merge-recursive das Format "every-codepath-needs-a-copy-of-all-special-case-code" verwendet.
t6404, t6423
: Verbesserte Handhabung von Umbenennen/Löschen im Ort-Backend erwarten
Abgezeichnet von: Elijah Newren
Wenn eine Datei umbenannt wird und inhaltliche Konflikte aufweist, hat merge-recursive nicht einige Stufen für den alten Dateinamen und einige Stufen für den neuen Dateinamen im Index; stattdessen kopiert es alle Stufen, die dem alten Dateinamen entsprechen, an die entsprechenden Stellen für den neuen Dateinamen, so dass es drei Stufen höherer Ordnung gibt, die alle dem neuen Dateinamen entsprechen.
Auf diese Weise ist es für den Benutzer einfacher, auf die verschiedenen Versionen zuzugreifen und den Konflikt aufzulösen (er muss nicht manuell ' git rm
' ( man ) die alte Version sowie ' git add
' ( man ) die neue).
Umbenennen/Löschen sollte ähnlich gehandhabt werden - es sollte zwei Stufen für die umbenannte Datei geben und nicht nur eine.
Wir wollen merge-recursive im Moment nicht destabilisieren und aktualisieren stattdessen die relevanten Tests, damit sie unterschiedliche Erwartungen haben, je nachdem, ob die " recursive
" oder " ort
Es werden "Merge"-Strategien angewandt.
Mit Git 2.30 (Q1 2021), Vorbereitung auf eine neue Merge-Strategie.
Ver Commit 848a856 , Commit fd15863 , 23bef2e übergeben , c8c35f6 übergeben , c12d1f2 übergeben , 727c75b übertragen , 489c85f übergeben , ef52778 übertragen , Übergabe f06481f (26. Oktober 2020) von Elijah Newren ( newren
) .
(Zusammengefasst von Junio C. Hamano -- gitster
-- in 66c62ea festlegen , 18. November 2020)
merge tests
: Erwartung einer verbesserten Behandlung von Verzeichnis-/Dateikonflikten in ort
Abgezeichnet von: Elijah Newren
merge-recursive.c
basiert auf der Idee, dass die unpack_trees()
und dann "kleine Nachbesserungen" vornehmen, um das Ergebnis zu erhalten.
Leider, unpack_trees()
wurde im Aktualisierungsmodus ausgeführt, was dazu führte, dass merge-recursive.c
zu folgen und mit einer sofortigen Bewertung und einem "Fix-it-up-as-you-go"-Design zu enden.
Einige Dinge, wie z.B. Verzeichnis-/Dateikonflikte, lassen sich in der Indexdatenstruktur nicht gut abbilden und erforderten speziellen Zusatzcode, um sie zu behandeln.
Als dann aber entdeckt wurde, dass Umbenennen/Löschen-Konflikte auch mit Verzeichnis-/Dateikonflikten einhergehen können, musste der spezielle Code für die Behandlung von Verzeichnis-/Dateikonflikten in den Umbenennen/Löschen-Codepfad kopiert werden.
...und dann musste es für Ändern/Löschen und für Umbenennen/Umbenennen(1zu2)-Konflikte kopiert werden, ...und trotzdem fehlten noch einige.
Als sich außerdem herausstellte, dass es auch Konflikte zwischen Dateien und Submodulen sowie zwischen Submodulen und Verzeichnissen gab, mussten wir den speziellen Code für die Behandlung von Submodulen auf alle Sonderfälle in der gesamten Codebasis übertragen.
Und dann wurde entdeckt, dass unsere Handhabung von Verzeichnis-/Dateikonflikten suboptimal war, weil sie nicht verfolgte Dateien erzeugte, um den Inhalt der konfliktbehafteten Datei zu speichern, die nicht bereinigt würden, wenn jemand ein ' git merge --abort
' ( man ) oder git rebase --abort
' ( man ) .
Es war auch schwierig oder beängstigend zu versuchen, die Indexeinträge zu diesen Dateien hinzuzufügen oder zu entfernen, da es im Index einen Konflikt zwischen Verzeichnis und Datei gab.
Aber die Veränderung merge-recursive.c
Die korrekte Behandlung dieser Konflikte war eine echte Qual, weil es im Code so viele Seiten mit ähnlichem, aber nicht identischem Code für die Behandlung von Verzeichnis-/Datei-/Submodulkonflikten gab, die alle aktualisiert werden mussten.
Ich habe hart daran gearbeitet, alle Verzeichnis-/Datei-/Submodulkonflikte in merge-ort über einen einzigen Codepfad zu behandeln und zu vermeiden, dass nicht verfolgte Dateien für die Speicherung verfolgter Inhalte erstellt werden (es werden zwar Dinge in alternativen Pfaden aufgezeichnet, aber es wird sichergestellt, dass sie übergeordnete Stufen im Index haben).
Mit Git 2.31 (Q1 2021) beginnt sich das Merge-Backend "richtig" zu entwickeln.
Beispiel:
Ver Übergabe 6d37ca2 (11 Nov 2020) von Junio C. Hamano ( gitster
) .
Siehe Commit 89422d2 , ef2b369 übergeben , 70912f6 übertragen , Commit 6681ce5 , Commit 9fefce6 , Übergabe bb470f4 , ee4012d übergeben , a9945bb übertragen , 8adffaa begehen , Übergabe 6a02dd9 , 291f29c übertragen , 98bf984 festlegen , 34e557a festlegen , Übergabe 885f006 , Übergabe d2bc199 , 0c0d705 festlegen , Übergabe c801717 , e4171b1 festlegen , 231e2dd übergeben , 5b59c3d übergeben (13. Dezember 2020) von Elijah Newren ( newren
) .
(Zusammengefasst von Junio C. Hamano -- gitster
-- in Übergabe f9d29da , 06. Januar 2021)
merge-ort
: Hinzufügen der Implementierung von record_conflicted_index_entries()
Abgezeichnet von: Elijah Newren
Nach checkout()
hat der Arbeitsbaum den entsprechenden Inhalt, und der Index stimmt mit der Arbeitskopie überein.
Das bedeutet, dass alle unveränderten und sauber zusammengeführten Dateien korrekte Indexeinträge haben, aber konfliktbehaftete Einträge müssen aktualisiert werden.
Dazu durchlaufen wir eine Schleife über die konfliktbehafteten Einträge und markieren den vorhandenen Indexeintrag für den Pfad mit CE_REMOVE
und fügt für den Pfad am Ende des Index neue Stufen höherer Ordnung hinzu (wobei die normale Indexsortierreihenfolge ignoriert wird), und entfernt dann am Ende der Schleife die CE_REMOVED-marked
Cache-Einträge und die Sortierung des Index.
Mit Git 2.31 (Q1 2021) wird die Erkennung von Umbenennungen zur "ORT"-Zusammenführungsstrategie hinzugefügt.
Ver 6fcccbd übergeben , Commit f1665e6 , 35e47e3 festlegen , Übergabe 2e91ddd , 53e88a0 übertragen , af1e56c übertragen (15. Dezember 2020), und Übergabe c2d267d , Commit 965a7bc , Übergabe f39d05c , e1a124e übergeben , 864075e übertragen (14. Dezember 2020) von Elijah Newren ( newren
) .
(Zusammengefasst von Junio C. Hamano -- gitster
-- in Commit 2856089 , 25. Januar 2021)
Beispiel:
merge-ort
: Implementierung der normalen Umbenennungsbehandlung hinzufügen
Abgezeichnet von: Elijah Newren
Implementierung der Behandlung von normalen Umbenennungen.
Dieser Code ersetzt den folgenden von merge-recurisve.c
:
- den entsprechenden Code für
RENAME_NORMAL
in process_renames()
- die
RENAME_NORMAL
Fall von process_entry()
Außerdem gibt es einigen gemeinsamen Code von merge-recursive.c
für mehrere verschiedene Umbenennungsfälle, die wir für diesen Fall (oder andere Umbenennungsfälle) nicht mehr benötigen:
handle_rename_normal()
setup_rename_conflict_info()
Die Konsolidierung von vier separaten Codepfaden zu einem einzigen wird durch eine Änderung des Designs ermöglicht: process_renames()
zwickt die conflict_info
Einträge innerhalb opt->priv->paths
tal que process_entry()
kann dann alle Arten von Konflikten, die keine Umbenennungen sind (Verzeichnis/Datei, Ändern/Löschen usw.) orthogonal behandeln.
Das bedeutet, dass es viel unwahrscheinlicher ist, dass wir eine spezielle Implementierung einer Kombination von Konflikttypen verpassen (siehe Commits, die von 66c62ea ("Merge branch 'en/merge-tests'", 2020-11-18, Git v2.30.0-rc0 -- zusammenführen aufgeführt in Los Nr. 6 ), insbesondere ef52778 übertragen ("merge tests: expect improved directory/file conflict handling in ort", 2020-10-26, Git v2.30.0-rc0 -- zusammenführen aufgeführt in Los Nr. 6 ) für weitere Einzelheiten).
Dies und die Tatsache, dass die Aktualisierung von Arbeitsbereich und Index orthogonal in der merge_switch_to_result()
Funktion vereinfacht den Code für verschiedene Sonderfälle der Umbenennung erheblich.
(Fairerweise muss man sagen, dass der Code für die Behandlung normaler Umbenennungen vorher nicht so kompliziert war, aber jetzt ist er noch viel einfacher).
Und, noch mit Git 2.31 (Q1 2021), Mit Git 2.31 (Q1 2021), lernt oRT Merge Strategie mehr Unterstützung für Merge Konflikte.
Ver 4ef88fc übergeben , 4204cd5 festlegen , 70f19c7 übertragen , Übergabe c73cda7 , Übergabe f591c47 , Übergabe 62fdec1 , 991bbdc übertragen , 5a1a1e8 festlegen , 23366d2 übertragen , 0ccfa4e übergeben (01 Jan 2021) von Elijah Newren ( newren
) .
(Zusammengefasst von Junio C. Hamano -- gitster
-- in Übergabe b65b9ff , 05. Februar 2021)
merge-ort
: Handhabung verschiedener Dateitypen im gleichen Pfad hinzufügen
Abgezeichnet von: Elijah Newren
Fügen Sie eine Behandlung hinzu, die ausdrücklich Kollisionen der folgenden Typen berücksichtigt:
- Datei/Submodul
- datei/symlink
- submodule/symlink> Da Konflikte am gleichen Pfad für die Benutzer schwer zu lösen sind, sollten Sie einen oder beide zur Seite schieben, so dass jeder seinen eigenen Pfad erhält.
Beachten Sie, dass im Falle einer rekursiven Behandlung (d. h.
call_depth > 0
), können wir einfach die Merge-Basis der beiden Merge-Basen als Merge-Ergebnis verwenden, so wie wir es bei Konflikten beim Ändern/Löschen, bei Binärdateien, bei widersprüchlichen Submodulwerten usw. tun.