Branch ist einfach, Merge eine Strafe!

Letzte Änderung am 22. April 2017 by Christoph Jüngling

Eine Umstellung von Subversion auf Mercurial ist wahrlich auch eine Umstellung für den Entwickler. Hier will ich aber mal schildern, warum man sowas vielleicht sogar freiwillig auf sich nimmt.

Es hätte so einfach sein können. Es ging “nur” um einen “Merge”, also die Verschmelzung zweier Entwicklungspfade mit dem Ziel, das Beste aus beiden Welten zu vereinen. Dieser Merge aus dem “Trunk” in einen “Branch” unter einem älteren Subversion-Server produzierte 158 Konflikte bei etwa der doppelten Anzahl an Dateien. Bedauerlicherweise existierte der Branch schon etwas länger.

Die Konflikte hätten größtenteils mit viel manuellem Aufwand gesichtet und aufgelöst werden müssen. Einige davon betrafen sogar Binärdateien, was den Merge für diese Dateien zu einer Entoder-Weder-Aktion machte und damit das Problem noch komplizierter als es ohnehin schon war.

Der “Trunk” (dt. “Stamm”) ist in Subversion (SVN) der Hauptentwicklungszweig, ein “Branch” (dt. “Zweig”) ist ein Nebenzweig. Während es nur einen Trunk gibt, kann es durchaus mehrere Branches geben. Normalerweise sollten Branches aber nur kurz Verwendung finden und schnell wieder gelöscht werden. Aber es gibt Ausnahmen.

Gut also, zwei Fehler sind hier schon mal direkt auszumachen: die “ältere SVN-Version” und der “längerlaufende Branch”. Dumm gelaufen, aber sowas kommt manchmal vor.

Da in dem Branch selbst seinerzeit recht wenig gearbeitet wurde, bevor etwas anderes wichtiger war, wäre auch der umgekehrte Weg möglich (und vielleicht einfacher) gewesen, aber es sollte ja nun mit dieser Aufgabe ordentlich weitergehen, und das auf dem aktuellen Stand.

Übernahme

Mir kamen die vielen Berichte aus dem WWW in den Sinn, wo die tollen Fähigkeiten von Mercurial oder Git gelobt werden, was das Merging anbetrifft. Also war der Gedanke naheliegend, den Merge einfach mit Mercurial durchzuführen. Leider bestand keine Möglichkeit, mittels der Mercurial-Extensions “hgsubversion” oder “convert” einen direkten Zugriff auf Subversion hinzubekommen, weil (wie gesagt) der SVN-Server dafür zu alt war. Nach einigem Überlegen entschloss ich mich, den nur ca. 12 Checkins zählenden Branch unter Mercurial nachzuspielen. Bei so wenig Änderungen kann man es sich leisten, das manuell zu machen. Dazu ging ich folgendermaßen vor:

  • Svn: Checkout der letzten gemeinsamen Revision des Trunks vor der Branch-Abspaltung in ein neues Arbeitsverzeichnis
  • Hg: Repository in diesem Arbeitsverzeichnis initialisieren, Extension “largefiles” aktivieren und konfigurieren, .hgignore erstellen und committen

Das Arbeitsverzeichnis beinhaltet nun also sowohl die Subversion- als auch die Mercurial-Repository-Informationen. Das bringt zwar unter Umständen die Overlay-Icons etwas durcheinander, aber das ist im Moment wirklich nicht wichtig. Darüberhinaus kommen die beiden Systeme sich nicht in die Quere, nur der Benutzer muss sich etwas mehr anstrengen, um den Überblick zu behalten.

Nun geht es weiter auf dem SVN-Trunk:

  • Erste Revision nach der Branch-Erstellung aus dem Trunk auschecken und mit originaler Checkin-Message, Autor und Datum von Svn in Mercurials “default branch” committen
  • Dito mit jeder weiteren Revision aus Svn, bis man an der Spitze des Trunks angekommen ist.

Nun kommt der Branch dazu. Dazu muss aber erst eine Vorbereitung gemacht werden:

  • Hg: Auf das zweite Changeset zurückgehen, einen Branch mit dem gleichen Namen wie in SVN (nicht zwingend, nur der Übersichtlichkeit halber) starten und committen.
  • Svn: Wechseln auf den Branch zu dessen erstem Checkin
  • Und nun wieder stückweise: In SVN eine Revision auschecken und diese in Hg mit originaler Checkin-Message, Autor und Datum von Svn in Mercurial committen, bis die Spitze des Branches erreicht ist.

Am Ende dieser Prozedur enthält das Mercurial-Repository genau die Changesets, die auch im SVN in diesem kurzen Abschnitt existieren.

Der eigentliche Merge

Nun beginnt die eigentliche Arbeit, bis hierher waren das nur Vorbereitungen. Da in Mercurial nun der letzte Stand aus dem Trunk im “default branch” steht, wird dessen Stand in den benannten Branch gemergt. (Das ist ein Deutsch, was?) Das ging erstaunlicherweise bis auf einen Mini-Konflikt völlig automatisch! Und dieser war absolut simpel aufzulösen.

Ein kurzer Test des entstandenen Quellcodes ergab zumindest keine Übersetzungsfehler. Unit-Tests wären jetzt natürlich eine tolle Sache, um sicherzustellen, dass auch wirklich noch alles funktioniert.

Probeweise habe ich dann den Branch wieder auf den “default branch” zurückgemergt, und siehe da, auch hier keine Probleme.

Fazit

Das ganze Prozedere hat etwas mehr als eine Stunde in Anspruch genommen und war im Endeffekt äußerst befriedigend. Im Falle einer größeren Anzahl von Checkins im ursprünglichen Subversion-Branch wäre auch ein kleines Programm möglich gewesen, das z.B. die Kommandozeilenbefehle svn.exe und hg.exe aufgerufen hätte.

Wäre das Projekt andererseits schon länger unter Mercurial verwaltet worden, dann wäre nicht einmal diese Stunde nötig gewesen. Die Arbeit hätte sich dann im Sekunden- bis Minutenbereich abgespielt.

SVN-User sagen oft: “Branching is easy, merging is pain!”

Und da fragt man sich unwillkürlich, warum man noch mit Subversion arbeitet :-)

Na, vielleicht gibt es demnächst ja hier einen Bericht zur Migration …

Ähnliche Artikel:

Schreibe einen Kommentar

Deine Email-Adresse wird nicht veröffentlicht.

neunzehn + acht =