Wie gehe ich eine komplizierte Zusammenführung an?

25

Hier ist der Deal, ich bin einer neuen Firma beigetreten und wurde gebeten, die Arbeit an einer Filiale abzuschließen, die seit fast einem Jahr nicht mehr berührt wurde. In der Zwischenzeit ist die Master-Branche stetig gewachsen. Idealerweise möchte ich alle Änderungen aus dem Master-Zweig in den Feature-Zweig zusammenführen und die Arbeit von dort aus fortsetzen, aber ich bin mir nicht sicher, wie ich das angehen soll.

Wie führe ich diese Zusammenführung sicher durch, während wichtige Änderungen auf beiden Seiten der Zweigstelle beibehalten werden?

Vlad Spreys
quelle
Vielen Dank an alle für das tolle Feedback. Ich werde git-imerge ausprobieren und wenn sich herausstellt, dass das chaotisch ist, werde ich einen neuen Zweigansatz verwenden!
Vlad Spreys
Kann jemand erklären, warum wir git cherry-pickhier nicht verwenden können ?
Santosh Kumar
1. Gebete. 2. Rebase. 3. Test. 4. zusammenführen.
AK_
1
Ich bevorzuge es, mich in dieser Situation neu zu orientieren, da es Commit für Commit gehen wird. Außerdem können Sie die neue Funktion komprimieren, bevor Sie den zusammengeführten Code verfügbar machen. YMMV.
Stephen

Antworten:

27

Die Kombination zweier (möglicherweise nicht kompatibler) Codeteile ist im Kern ein Entwicklungsproblem und kein Problem der Versionskontrolle . Der Befehl Git merge kann bei diesem Vorgang hilfreich sein, hängt jedoch von der Form des Problems ab.

Am sinnvollsten ist es, beide Versionen zuerst mit der Basis zu vergleichen. Dies gibt Ihnen eine Vorstellung von der besten Strategie, um dies voranzutreiben. Ihr Ansatz kann je nach Art und Überlappung der Änderungen in den einzelnen Zweigen unterschiedlich sein.

Stellen Sie sich das ideale Szenario vor: Sie werden feststellen, dass der Hauptzweig und der Feature-Zweig jeweils nur sich gegenseitig ausschließende Teile des Codes modifiziert haben, sodass Sie einfach alle Änderungen in festschreiben und loslegen können.

Natürlich wird das mit ziemlicher Sicherheit nicht der Fall sein, aber die Frage ist: Wie weit ist es von diesem idealen Szenario entfernt? dh wie vermischt sind die Veränderungen?

Wie ausgereift war der alte Feature-Zweig? War es in einem guten Arbeitszustand oder nicht (oder unbekannt)? Wie viel der Funktion wurde beendet?

Wenn sich der relevante Code in der Hauptniederlassung im letzten Jahr stark geändert hat oder die Funktion noch nicht sehr ausgereift ist, kann es sinnvoll sein, eine neue Verzweigung der neuesten Version zu erstellen und die alte Funktion manuell wieder einzubinden. Auf diese Weise können Sie schrittweise vorgehen, um es zum Laufen zu bringen.

Wenn Sie eine chaotische Zusammenführung von viel Code durchführen und dieser nicht funktioniert, ist das Debuggen ziemlich schwierig. Wenn sich der Hauptzweig im letzten Jahr stark verändert hat, sind möglicherweise größere Designänderungen an der Funktion erforderlich, damit sie funktioniert. Es wäre nicht angebracht, diese Änderungen über "Konflikte lösen" vorzunehmen, da dies erfordern würde, alle Änderungen auf einmal vorzunehmen und zu hoffen, dass es funktioniert. Dieses Problem würde durch die Möglichkeit von Fehlern im alten, teilweise fertigen Zweig noch verschärft.


quelle
+1 "Ich könnte in Betracht ziehen, eine neue Abzweigung der neuesten Version zu erstellen und die alte Funktion manuell wieder einzubauen"
mika
1
Die erste Schlüsselfrage lautet: Wird der alte Feature-Zweig erstellt? Läuft es? Wenn nicht, wird es sehr schwierig sein, Ihre Zusammenführung zu testen.
19.
22

In meiner begrenzten Git-Erfahrung kann ich sagen, dass es manchmal schneller ist, den Feature-Zweig erneut zu starten, wenn der Master zu weit vom Ablösepunkt entfernt ist.

Das Zusammenführen von zwei Zweigen ohne Kenntnis des Verlaufs des Codes (vorausgesetzt, Sie sind gerade dem Projekt beigetreten) ist sehr schwierig, und ich wette, dass selbst ein Entwickler, der das Projekt von Anfang an verfolgt hat, bei der Zusammenführung wahrscheinlich einige Fehler machen würde.

Dies ist natürlich sinnvoll, wenn der Feature-Zweig nicht sehr groß ist. Sie können jedoch einfach den alten Feature-Zweig geöffnet lassen, erneut vom Master verzweigen und die Änderungen , aus denen das Feature besteht, manuell erneut einführen . Ich weiß, dass dies der manuellste Ansatz ist, aber Sie haben die vollständige Kontrolle über fehlende oder verschobene Codes.

In diesem Fall ist die Paarprogrammierung mit einem erfahrenen Programmierer das beste Szenario, damit Sie den Code besser kennenlernen können.
Es könnte sich sogar als schneller herausstellen, wenn Sie Zusammenführungskonflikte und Testzeiten berücksichtigen!

Ich bin ein bisschen davon ausgegangen, dass zumindest der Versuch einer Zusammenführung offensichtlich das Beste ist. Wenn dies fehlschlägt oder sich als zu schwierig herausstellt, versuchen Sie es mit der Kirschernte. Wenn dies nicht funktioniert, gehen Sie manuell vor.

GavinoGrifoni
quelle
2
Auf jeden Fall nicht der richtige Ansatz.
Andy
12
Nein, dies ist der richtige Ansatz. Wenn Sie einen alten Zweig haben und den Code nicht kennen, wird der Versuch, ihn zusammenzuführen, nicht sehr erfolgreich und sehr riskant sein. Bestimmen Sie die ursprünglich vorgenommenen Änderungen, überprüfen Sie, ob sie überhaupt für den neuen Code relevant sind, und wenden Sie sie dann sinnvollerweise an. Dies ist ein manueller Ansatz, aber unter diesen Umständen der einzig sichere. Natürlich würde ich immer noch zuerst eine Zusammenführung versuchen, nur um zu sehen, was passiert, und ich würde das Protokoll überprüfen, um zu sehen, wie viel Änderungen auch in der Verzweigung vorgenommen wurden - könnte trivial sein.
gbjbaanb
10
@ DavidPacker: Ich glaube nicht, dass GavianoGrifoni vorschlägt, die ganze Arbeit über Bord zu werfen. Er schlägt vor, die Änderungen aus der alten Filiale schrittweise manuell in die aktuelle Entwicklungslinie zu übernehmen. Das wird die alte Geschichte wegwerfen , nicht mehr.
Doc Brown
3
@DavidPacker 1. Die Filiale ist ein Jahr veraltet, 2. Der Typ, der damit beauftragt ist, den Code fertigzustellen, kennt ihn überhaupt nicht. Angesichts dieser beiden Faktoren ist eine manuelle erneute Anwendung der einzig realistische Weg, um die Aufgabe anzugehen. Niemand schlägt ein einfaches Kopieren und Einfügen der Spitzenrevision des alten Zweigs vor.
gbjbaanb
5
@DavidPacker: Zusammenführungskonflikte können schlimm werden - wenn Sie 500 davon sofort lösen müssen, bevor Sie das Programm wieder in einen kompilierbaren und testbaren Zustand versetzen. Dies ist die Situation, die das OP hier erwartet. Wenn Sie der Meinung sind, dass es möglich ist, Git effizient einzusetzen, um diese "Alles-oder-Nichts" -Situation zu vermeiden, warum bearbeiten Sie Ihre Antwort nicht und teilen dem OP mit, wie dies erreicht werden kann?
Doc Brown
16

git-imerge ist genau für diesen Zweck konzipiert. Es ist ein Git-Tool, das eine Methode zum inkrementellen Zusammenführen bereitstellt . Durch schrittweises Zusammenführen müssen Sie sich nur mit den Kollisionen zwischen zwei Versionen befassen, niemals mehr. Darüber hinaus kann eine weitaus größere Anzahl von Zusammenführungen automatisch durchgeführt werden, da die einzelnen Änderungssätze kleiner sind.

Joe
quelle
6

Der Versuch, den Hauptstrangkopf mit einem jahrelangen Ast zu verschmelzen, kann frustrierend sein und die Beule auf dem Schreibtisch mit der Stirn vertiefen.

Die Hauptleitung kam im Laufe der Monate nicht in einem Durchgang an den Ort, an dem sie sich befand. Es hatte auch Entwicklung und Releases. Der Versuch, alles auf den neuesten Stand zu bringen, kann überwältigend sein.

Beginnen Sie stattdessen mit dem Zusammenführen ab dem ersten Feature, das nach dem Aufteilen des veralteten Zweigs wieder in der Hauptlinie zusammengeführt wird. Lass die Fusion funktionieren. Dann wird das nächste Feature zusammengeführt. Und so weiter. Viele dieser Feature-Merges werden ohne Konflikte zusammengeführt. Es ist immer noch wichtig, sicherzustellen, dass die aktuelle Funktionalität des veralteten Zweigs mit der Richtung, in die die Hauptleitung gegangen ist, kompatibel bleibt.

Möglicherweise möchten Sie vom Kopf des veralteten Zweigs zur Rolle des Zusammenführens bei anderen Änderungen verzweigen. Hier geht es mehr darum, sicherzustellen, dass die Commits und die Historie, wenn jemand darauf zurückblickt, klar sind und die Rolle und die Richtlinien der einzelnen Zweige kommunizieren. Der veraltete Zweig war ein Feature-Zweig. Das, von dem aus Sie arbeiten, ist ein Akkumulations- und Versöhnungszweig.

Vieles davon wird einfacher, wenn die alten Feature- oder Release-Zweige noch da draußen existieren und leicht zugänglich sind (einige Orte haben die Richtlinie, die Namen von Zweigen zu bereinigen, die älter als ein bestimmtes Datum sind, damit die Liste der Zweige nicht überfüllt ist ).

Das Wichtigste dabei ist, dass Sie sicherstellen, dass Sie alle Teile des Hauptverlaufs nach dem erfolgreichen Zusammenführen testen und korrigieren. Auch wenn etwas ohne Konflikte verschmelzen kann, bedeutet dies nur, dass der Code nicht in Konflikt geraten ist. Wenn die Art und Weise, in der auf die veraltete Funktion zugegriffen wurde, veraltet oder entfernt wurde, müssen nach dem erfolgreichen Zusammenführen möglicherweise Korrekturen vorgenommen werden.

Dies funktioniert übrigens auch für andere Versionskontrollsysteme. Ich musste gelegentlich eine bestimmte Gruppe von SVN-Commits in einem Zweig (Cherry Picking) für ein Feature zusammenführen, den Zweig für dieses Feature reparieren und dann die nächste Gruppe von SVN-Commits zusammenführen, anstatt nur einen Wholesale-SVN durchzuführen verschmelzen.

Man kann hier zwar ein Git-Cherry-Pick machen und es erlaubt, bestimmte Commits einzubringen, dies hat jedoch einige Nachteile, die den Prozess möglicherweise komplizieren. Der Cherry Pick zeigt keine Informationen zu dem Commit an, aus dem Sie ausgewählt haben (Sie können ihn an die Commit-Nachricht anhängen). Dadurch wird es schwieriger, die Commits in der Historie tatsächlich zu verfolgen.

Darüber hinaus bedeutet dies, dass Sie den Master nicht effektiv auf dem veralteten Zweig wiedergeben - Sie werden möglicherweise unvollständige Features auswählen - und diese Features werden möglicherweise nicht in der richtigen Reihenfolge wiedergegeben.

Der Hauptgrund, warum man historische Commits zusammenführen sollte, um den veralteten Zweig zu meistern, besteht darin, in der Lage zu sein, den "zukünftigen Verlauf" des veralteten Zweigs in einem Zustand zu halten, über den man nachdenken kann. Sie können die Zusammenführungen aus dem Verlauf auf den veralteten Zweig und die Korrekturen zur Wiedereingliederung der Funktionalität deutlich sehen. Die Features werden in derselben Reihenfolge hinzugefügt, in der sie erstellt wurden. Und wenn Sie fertig sind und die Zusammenführung vom Chef des Masters zum veralteten Zweig abgeschlossen haben, wissen Sie, dass alles zusammengeführt wurde und Sie keine Commits mehr verpassen.


quelle
+1 Dies ist eine interessante potenzielle alternative Lösung, die die Zusammenführung verwendet, um große Änderungen einzubeziehen. Ich sehe jedoch einen Nachteil: Angenommen, Sie haben Hauptversionen von ABCDE und möchten den Feature-Zweig A1 in E integrieren. Möglicherweise ist es sehr aufwändig, den Code in BC und D zusammenzuführen. Was wäre, wenn D in E wäre? eine große Designänderung, die die inkrementellen Änderungen in B, C und D irrelevant machte? Auch hier kommt es wieder darauf an, wie ausgereift das Feature überhaupt war. Ein nützlicher möglicher Ansatz, aber seine Angemessenheit muss vor dem Start berücksichtigt werden.
1

Schritt 1. Erfahren Sie mehr über den Code, analysieren Sie seine Architektur und die Änderungen, die seit dem letzten gemeinsamen Vorfahren in beiden Zweigen vorgenommen wurden.

Schritt 2. Wenn die Funktion weitgehend unabhängig erscheint und hauptsächlich verschiedene Bereiche des Codes berührt, Konflikte zusammenführt, behebt, testet, behebt usw. Das ist der glückliche Weg, Sie sind ziemlich gut zu gehen. Fahren Sie andernfalls mit Schritt 3 fort

Schritt 3. Analysieren Sie die Konfliktbereiche, verstehen Sie die funktionalen Auswirkungen und Gründe im Detail. Es kann leicht zu Konflikten bei den Geschäftsanforderungen kommen, die hier zutage treten. Besprechen Sie dies mit BAs und anderen Entwicklern. Machen Sie sich ein Bild von der Komplexität der Störungsbeseitigung.

Schritt 4. Entscheiden Sie im Lichte des oben Gesagten, ob Sie nur diejenigen Teile zusammenführen / auswählen / sogar ausschneiden / einfügen möchten, die nicht in Konflikt stehen, und die in Konflikt stehenden Teile neu schreiben möchten, ODER ob Sie das gesamte Feature von Grund auf neu schreiben möchten .

Brad Thomas
quelle
0

1. Wechseln Sie zu dem Zweig, der als Hauptzweig für Entwickler / Releases verwendet wird.

Dies ist der Zweig, der die neuesten Änderungen am System enthält. Kann sein master, core, devhängt es von der Firma. In deinem Fall ist es wahrscheinlich masterdirekt.

git checkout master
git pull

Ziehen Sie, um sicherzustellen, dass Sie die neueste Version des Hauptentwicklungszweigs erworben haben.

2. Gehen Sie zur Kasse und ziehen Sie den Zweig heraus, der die Arbeit enthält, die Sie erledigen möchten.

Sie ziehen, um sicherzustellen, dass Sie tatsächlich die neuesten Inhalte der Branche haben. Indem Sie es direkt auschecken, ohne es zuerst lokal zu erstellen, stellen Sie sicher, dass die neuen Inhalte master(bzw. der Haupt-Dev-Zweig) nicht darin enthalten sind.

git checkout <name of the obsolete branch>
git pull origin <name of the obsolete branch>

3. Führen Sie den Hauptentwicklungszweig zum veralteten Zweig zusammen.

Bevor Sie den folgenden Befehl ausführen, stellen Sie sicher, entweder durch Eingabe git branchoder git statusdass Sie auf dem veralteten Zweig sind.

git merge master

Das git merge Befehl versucht, den Inhalt aus dem angegebenen Zweig zusammenzuführen, in diesem Fall aus dem Zweig, in masterdem Sie sich gerade befinden.

Betonung wird versuchen , zu . Es kann zu Zusammenführungskonflikten kommen, die nur von Ihnen und von Ihnen gelöst werden müssen.

4. Korrigieren Sie die Zusammenführungskonflikte, führen Sie einen Commit durch und verschieben Sie die Konfliktkorrektur

Nachdem Sie den Zusammenführungskonflikt in allen Dateien behoben haben, müssen Sie die Konfliktlösung bereitstellen und verschieben origin.

git add .
git commit -m "fixed the merge conflict from the past year to update the branch"
git push

Sie können in der Regel anrufen git add . alle Dateien zum Festschreiben bereitstellen. Wenn Sie sich mit Zusammenführungskonflikten befassen, möchten Sie, dass alle erforderlichen Dateien aktualisiert werden.

Zusätzliche Anmerkung

Das Lösen von Zusammenführungskonflikten kann eine mühsame Arbeit sein. Vor allem, wenn Sie neu in einem Unternehmen sind. Möglicherweise verfügen Sie noch nicht einmal über das erforderliche Wissen, um alle Zusammenführungskonflikte alleine zu lösen.

Nehmen Sie sich Zeit, um alle aufgetretenen Konflikte sorgfältig zu untersuchen und zu beheben, bevor Sie mit Ihrer Arbeit fortfahren.


Es kann also vorkommen, dass Sie mit der Arbeit an einem einjährigen Zweig beginnen, den aktuellen Entwicklungsstand darin zusammenführen und überhaupt keine Zusammenführungskonflikte haben.

Dies geschieht, wenn sich das System im Laufe des Jahres stark verändert hat, aber niemand die Dateien berührt hat, die in der einjährigen Filiale tatsächlich geändert wurden.

Andy
quelle
6
# 4 ist möglicherweise das Problem. Wenn im letzten Jahr viele Änderungen vorgenommen wurden, sind möglicherweise größere Änderungen an der alten Funktion erforderlich. Wenn Sie dies durch Zusammenführen tun, müssen Sie den Code auf einen Schlag grundlegend ändern und hoffen, dass er funktioniert. Dies ist keine gute Entwicklungspraxis. Und wer weiß, wie der Status des unvollendeten Features war? Es kann vorkommen, dass Sie durcheinander mit nicht funktionierendem Code kommen und wer weiß, ob dies auf Probleme mit dem Original oder auf vorgenommene Änderungen zurückzuführen ist?
David, solange dieser Standardansatz funktioniert, ist er in Ordnung, und das OP sollte dies zuerst versuchen. Es besteht jedoch definitiv die Gefahr, dass in der beschriebenen Situation zu viele Zusammenführungskonflikte auftreten, um mit ihnen auf diese "Alles-oder-Nichts" - Weise umzugehen.
Doc Brown
@ dan1111 Dass es Zusammenführungskonflikte gibt, ist völlig in Ordnung, und tatsächlich ist es der richtige Weg, sie zu durchlaufen. Da der Zweig ein Jahr lang unberührt blieb, können Sie sich ziemlich sicher sein, dass er nicht so wichtig ist und keinen großen Teil des Systems beeinträchtigt. Obwohl der Zweig ein Jahr hinterher ist, können Sie also nur 2 bis keine Zusammenführungskonflikte erhalten.
Andy
4
Die Annahme, dass dieser Zweig unwichtig ist, ist nicht gerechtfertigt. Es könnte eine grundlegende Designänderung gewesen sein, die aufgegeben wurde und nun wieder aufgegriffen wird. Es könnte alles sein. Sie haben Recht, dass es sich um eine einfache Angelegenheit handeln könnte und dass es nur wenige oder gar keine Konflikte geben könnte. In diesem Fall wäre Ihre Antwort richtig. Das ist aber nicht die einzige Möglichkeit.
@ dan1111 Wenn jemand eine Feature-Stelle in einer separaten Filiale seit einem Jahr nicht mehr berührt hat, werden Systemänderungen nicht mehr so ​​stark berücksichtigt. Dies ist auf meine eigenen Erfahrungen mit veralteten (über 6 Monate alten) Branchen zurückzuführen.
Andy