Strategien zum Zusammenführen von 1 Jahr Entwicklungszeit in Visual Studio

32

Ich habe einen Kunden, der darauf bestand, dass wir unsere Neuentwicklung für das gesamte Jahr 2016 von den Hauptbranchen getrennt halten. 3-4 andere Teams arbeiteten in verschiedenen Kapazitäten an der Anwendung. Es wurden zahlreiche große Änderungen vorgenommen (Änderung der Art der Abhängigkeitsinjektion, Bereinigung des Codes mit ReSharper usw.). Es ist mir nun überlassen, main in unseren neuen Entwicklerzweig zu integrieren, um unsere Änderungen voranzutreiben.

Bei meinem ersten Zusammenführungszug hat TFS ~ 6500 Dateien mit Konfliktlösung gemeldet. Einige davon werden einfach sein, aber einige werden viel schwieriger sein (insbesondere einige der Javascript-, API-Controller und Dienste, die diese Controller unterstützen).

Gibt es einen Ansatz, mit dem ich es mir leichter machen kann?

Um dies zu verdeutlichen, habe ich mich auf meinem Weg mehrfach mit diesem Ansatz befasst. Der Kunde war und ist sich der Schwierigkeiten bewusst. Da sie sich für einen Mangel an QA-Mitarbeitern entschieden hatten (1 Tester für 4 Entwickler, keine automatisierten Tests, wenig Regressionstests), bestanden sie darauf, dass wir unsere Niederlassung von den Änderungen in der Hauptniederlassung isoliert halten, unter dem Vorwand, dass dies den Bedarf für unsere verringern würde Tester über Änderungen zu wissen, die an anderer Stelle vorgenommen werden.

Eines der größeren Probleme ist ein Upgrade auf die eckige Version und einige andere Software von Drittanbietern - leider haben wir keine gute Möglichkeit gefunden, diese Lösung zu erstellen, bis alle Teile wieder in Position gebracht sind.

user258451
quelle
63
Nee. Sie haben zwei separate Niederlassungen, die ein Jahr lang aktiv entwickelt wurden. Die Verschmelzung wird scheiße sein.
17 von 26
2
Inwieweit hat Ihr Team Änderungen vorgenommen? Es ist möglicherweise effizienter, diese Änderungen zu identifizieren und sie dann manuell erneut auf die aktuelle Master-Codebasis anzuwenden.
kdgregory
2
Ist es das ganze Jahr 2015 oder 2016? Wenn es 2015 ist, sind es 2 Jahre, was bedeutet, dass es doppelt saugt.
David sagt Reinstate Monica
1
Warum kümmert es den Kunden, wenn sich die Arbeit, die Sie für ihn erledigen, in einem separaten Zweig Ihres Versionskontrollsystems befindet?
Ixrec
17
Was auch immer Sie tun, stellen Sie sicher, dass Sie stündlich abrechnen.
Sean McSomething

Antworten:

37

Es hätte einen einfachen Weg gegeben, der Ihre neue Entwicklung von der Hauptniederlassung getrennt gehalten hätte, ohne Sie in diese unglückliche Situation zu bringen: Jede Änderung vom Stamm hätte täglich in Ihrer Entwicklungsniederlassung zusammengeführt werden müssen . (War Ihr Kunde wirklich so kurzsichtig, dass er nicht damit rechnen konnte, dass Ihre Niederlassung eines Tages wieder in die Hauptleitung zurückgeführt werden muss?)

Wie auch immer, der beste Ansatz ist meiner Meinung nach, zu wiederholen, was aus erster Hand hätte passieren sollen:

  • Identifizieren Sie die Semantik der Änderungen in der Hauptzeile für Tag 1 nach der Erstellung der Verzweigung. Wenden Sie sie so gut wie möglich auf Ihre aktuelle Codebasis an. Wenn es sich um eine "lokale Änderung" handelte, sollte es einfach sein. Wenn es sich um eine "übergreifende Umgestaltung" handelte, wie das Umbenennen einer häufig verwendeten Klasse, wenden Sie diese semantisch gleichwertig auf Ihre aktuelle Codebasis an. Hoffentlich wurden in diesem Jahr keine widersprüchlichen Änderungen an der Codebasis für "Ihren" Zweig vorgenommen, da dies sonst zu einem echten Rätsel werden kann
  • Testen Sie das Ergebnis (Habe ich erwähnt, dass Sie für diese Aufgabe eine gute Testsuite benötigen)? Beheben Sie alle im Test aufgedeckten Fehler
  • Wiederholen Sie diesen Vorgang für die Änderungen in der Hauptzeile für Tag 2, dann für Tag 3 usw.

Dies kann funktionieren, wenn die Teams die klassischen Regeln der Versionskontrolle strikt einhalten ("Nur kompilierbare, getestete Status festschreiben" und "Früh und häufig einchecken").

Nach 365 Wiederholungen (oder 250, wenn Sie Glück haben und die Arbeit für Wochenendänderungen bündeln können) sind Sie fast fertig (fast, weil Sie die Anzahl der Änderungen hinzufügen müssen, die während des Integrationszeitraums an der Hauptleitung vorgenommen werden ). Der letzte Schritt ist das Zusammenführen des aktualisierten dev-Zweigs in den Trunk (damit Sie den Verlauf des Trunks nicht verlieren). Das sollte einfach sein, denn technisch sollte es nur ein Ersatz der betroffenen Dateien sein.

Und ja, ich meine es ernst, es gibt wahrscheinlich keine Abkürzung dazu. Es könnte sich herausstellen, dass "tägliche Portionen" manchmal zu klein sind, aber ich würde das nicht erwarten, ich denke, es ist wahrscheinlicher, dass tägliche Portionen zu groß werden. Ich hoffe, Ihr Kunde bezahlt Sie wirklich gut dafür und das ist für ihn so teuer, dass er aus seinem Scheitern lernen wird.

Ich sollte hinzufügen, dass Sie dies auch mit vertauschten Seiten versuchen können - indem Sie die Änderungen von Ihrem Zweig in kleinen Portionen wieder in die Hauptlinie integrieren. Dies ist möglicherweise einfacher, wenn in Ihrem Entwicklungszweig viel weniger Änderungen vorgenommen wurden als im Trunk, oder wenn die meisten Änderungen in neuen Quelldateien vorgenommen wurden, die derzeit nicht zum Trunk gehören. Man kann dies als "Portierung" einer Funktion von einem Produkt A (dem Dev-Zweig) zu einem etwas anderen Produkt B (dem aktuellen Status des Trunks) ansehen. Wenn die Mehrheit der übergreifenden Refactorings jedoch in der Hauptzeile durchgeführt wurde und sich auf Ihren neuen Code auswirkt (die 6500-Zusammenführungskollisionen scheinen ein Beweis dafür zu sein), ist es möglicherweise einfacher, wie ich es zuerst beschrieben habe.

Doc Brown
quelle
9
Wenn Sie während der Wiedereingliederung die Entwicklung am Stamm fortsetzen, empfehle ich, zuerst die Stammspitze abzweigen und daraus zu entwickeln. Ansonsten verschmelzen Vergangenheit und Zukunft effektiv gleichzeitig. Aber ich verlasse mich auf Doc Brown, wenn Raum-Zeit-Diskontinuitäten auftreten.
Radarbob
1
@radarbob: was du vorschlägst, macht nur Sinn, wenn das OP von dev zu trunk integriert, aber nicht, wenn er sich entscheidet, von trunk zu dev zusammenzuführen, wie ich es zuerst beschrieben habe. Wenn das OP täglich Änderungen von Trunk zu seinem Entwicklerzweig überträgt (beginnend mit Änderungen an 365 Tagen in der Vergangenheit), spielt es keine Rolle, ob die Entwicklung auf dem Trunk fortgesetzt wird. Er muss diese Taktik nur fortsetzen, bis er die Gegenwart erreicht (vorausgesetzt, er kann die Änderungen dieser 3-4 Teams an einem Tag in weniger als einem Tag integrieren und testen).
Doc Brown
Zitat: "Ich sollte hinzufügen, dass Sie dies auch mit getauschten Seiten versuchen können - die Änderungen von Ihrer Niederlassung in täglichen Bündeln wieder in die Hauptleitung integrieren. " Ich spüre eine mögliche Kaskade von "harmonischen Resonanzverzerrungen" mit widersprüchlichen Veränderungsintegrationen.
Radarbob
Das ist ein guter Rat. Unter Bearbeiten finden Sie einige Informationen.
user258451
1
@ user258451: also gab es verschiedene QA-teams für den trunk und den neuen dev branch, die nicht miteinander sprechen wollten? Great Scott: - ((
Doc Brown
14

In dieser Phase der Zusammenführung würde ich sagen, dass das automatische Zusammenführen den Prozess möglicherweise nur übermäßig kompliziert macht. Ich hatte ähnliche Probleme mit Zweigen, die seit über einem Jahr auseinander gegangen sind, und die effektivste Methode, die ich habe, ist Folgendes:

  • Nehmen Sie eine Kopie des ursprünglichen, nicht zusammengefügten Zustands
  • Unterscheiden Sie zwischen dem nicht zusammengeführten und dem neuesten
  • Zerlegen Sie alle gemeinsamen Elemente
    • Nehmen Sie beispielsweise alle Funktionsnamen- und anschließend Parameteränderungen usw. vor.
    • Ignorieren Sie Leerzeichen auf Diff, wenn sich die Standards geändert haben, da Sie sonst viel Zeit damit verschwenden, Leerzeichen zu zählen
  • Konzentrieren Sie sich zuerst auf die Kernfunktionalität

Eventuell werden Compiler-Warnungen und die Diffs Ihre besten Freunde sein. Verwenden Sie weiterhin das nicht zusammengeführte Diff, um genau zu sehen, was anders war, und fahren Sie einfach fort. Möglicherweise gibt es verschiedene Tools, mit denen Sie helfen können, aber es liegt an Ihnen, das Beste zu finden.

Der Schlüssel ist, weiterzumachen.

Bearbeiten:

Dieser Ansatz bedeutet, dass der Versionskontrollverlauf "beschädigt" wird, da Sie die Beweise für die Zusammenführung von Zweig zu Zweig sowie den Verlauf des nicht zusammengeführten Zweigs verlieren.

Dank an Kommentare von 'Jack Aidley' und '17 von 26 '

Erdrik Ironrose
quelle
1
Das Hauptproblem bei diesem Ansatz besteht darin, dass die Aufzeichnung der im Versionskontrollsystem verbleibenden Änderungen zerstört wird.
Jack Aidley
Wenn Sie während des Zusammenführens ein zweites Mal dieselben Änderungen vornehmen, haben Sie immer noch ein Protokoll der Änderungen. Diese werden nur in der Reihenfolge ausgeführt, in der sie zusammengeführt wurden, und nicht in der Reihenfolge, in der sie während der Entwicklung ausgeführt wurden. Nicht ideal, aber besser als nichts. Außerdem hätten Sie immer noch den ursprünglichen, nicht zusammengeführten Status, wenn dieser in der Versionskontrolle beibehalten würde.
Erdrik Ironrose
Sie hätten ein Protokoll der Änderungen, aber Sie hätten keine historischen Beweise dafür, dass die Änderungen von Zweig zu Zweig zusammengeführt wurden. Dies wäre in TFS ein riesiger Deal, da Sie beim Zusammenführen von Zweig zu Zweig nur aus den nicht zusammengeführten Änderungssätzen auswählen können.
17 von 26
@ 17of26 Obwohl ich damit einverstanden bin, dass Sie einige Änderungsaufzeichnungen wiederherstellen können, ist 17 von 26 richtig, dass diese Aufzeichnungen nicht vollständig oder genau sind. Es mag sein, dass dieser Ansatz so einfach ist, dass dieser Verlust von Daten angesichts der schlechten Situation, in der sie sich gerade befinden, zu einem akzeptablen Kompromiss wird. Ich denke jedoch, dass es ein wichtiger Nachteil ist, zu erkennen, unabhängig davon, was sie entscheiden.
Jack Aidley
1
@Jack Aidley Ich stimme definitiv zu, dass es das Problem ist, also habe ich meiner Antwort ein bisschen hinzugefügt, um darüber nachzudenken. Ich hoffe das ist in ordnung
Erdrik Ironrose
8

Vor ein paar Jahren hatten wir einen Kunden mit den gleichen Anforderungen, Filialen getrennt zu halten. Also haben wir es getan.

Wir haben ihren Zweig nie wieder zusammengelegt. Sie hatten dort eine eigene einzigartige Version. Wir haben ihnen zusätzliche Gebühren für Änderungen berechnet, da wir im Wesentlichen zwei Hauptstämme anstelle von einem Hauptstamm und Zweigen hatten.

Wir haben versucht, wieder zum Kofferraum zurückzukehren, aber nach zwei Wochen haben wir uns entschlossen, diese Anstrengung aufzugeben, da es stundenlang ohne greifbare Vorteile war.

Also nicht wieder zusammenführen. Führen Sie künftig wichtige Korrekturen für diesen Client-Zweig nach Bedarf zusammen, und alle Verbesserungen werden nur einmalig für diesen Client berechnet.

Jon Raynor
quelle
Diese Strategie ist nur durchführbar, wenn die verschiedenen Entwicklungslinien unterschiedliche Kunden ansprechen. Oder, wenn die Anwendungsfälle, in denen das Produkt betroffen ist, es ermöglichen, die beiden verschiedenen Produktlinien in nicht integrierter Weise parallel zu verwenden. Nach meinem Verständnis beschreibt das OP eine Situation, in der die neue Entwicklungslinie auf denselben Kunden abzielt wie derjenige, der den Trunk verwendet, und es ist unklar, ob die parallele Verwendung von zwei Produktlinien für seinen Fall einen Sinn ergeben könnte.
Doc Brown
1

Es wird keinen Spaß machen, aber wie schmerzhaft es sein wird, hängt von der Art der Veränderungen ab und davon, wie isoliert sie sind.

Ich schlage vor, Sie versuchen, die Zweige durch Umgestaltung so weit wie möglich zusammenzuführen, bevor Sie eine tatsächliche Zusammenführung durchführen.

Das Merge-Tool ist ein bisschen dumm, weil es nur textuelle Unterschiede betrachtet und den Code in keiner Weise versteht. Wenn der Hauptzweig den Namen einer Klasse geändert hat, die in der gesamten Anwendung verwendet wird, und der Feature-Zweig den alten Namen in neuem Code verwendet, kann das Zusammenführungstool nicht erkennen, dass der Klassenname auch im neuen Code geändert werden sollte. Wenn Sie jedoch in Zweig B ein Refactoring durchführen, um die Klasse wie in Zweig A umzubenennen, funktioniert dies sowohl im alten als auch im neuen Code, und die Zusammenführung verläuft reibungslos.

Zweitens sollten Sie überprüfen, wie lokalisiert die Änderungen im Entwicklungszweig sind. Wenn die Änderungen im Feature-Zweig auf wenige Bereiche beschränkt sind, müssen Sie den nicht betroffenen Code nicht konvergieren, sondern können ihn einfach aus dem Hauptzweig kopieren und überschreiben.

In Codebereichen, in denen in beiden Zweigen nicht unbedeutende Änderungen vorgenommen wurden, müssen Sie den Code sorgfältig prüfen und entscheiden, wie er neu geschrieben werden soll.

JacquesB
quelle