Apache Subversion: Feature Branches

von Hubert Schmid vom 2012-12-09

Es gibt bei Apache Subversion zwei typische Anwendungsfälle für Entwicklungszweige: Release Branches und Feature Branches. Beide Typen haben einige Gemeinsamkeiten. Im Detail unterscheiden sich aber sowohl die Vorgehensweise als auch die verwendeten Befehle entscheidend.

Die Einsatzszenarien für Release Branches sind relativ intuitiv. Anders verhält es sich aus meiner Sicht mit Feature Branches: Sie werden häufig falsch eingesetzt und verursachen dadurch unnötige Probleme und Mehrarbeit. Das lässt sich vermeiden, indem man sich ihre folgenden Eigenschaften vor Augen führt:

Damit eignen sich Feature-Branches erstens für experimentelle Änderungen und Varianten, bei denen sich erst im Rahmen der Entwicklung entscheidet, ob sie übernommen werden, zweitens für Änderungen, die anderen Projektbeteiligten vor der Übernahme in den originären Branch zugänglich gemacht werden sollen, drittens für langlaufende Änderungen, die nicht inkrementell auf dem originären Branch zu machen sind, sowie viertens für Kombinationen dieser Punkte. Gute Einsatzszenarien sind Änderungen, die weit über den Quellcode gestreut sind, wie beispielsweise der Wechsel der Datenbanktechnologie oder der Austausch einer Logging-Bibliothek.

Und so funktioniert es:

create

Wie jeden anderen Branch sollte man auch den Feature-Branch stets direkt im Repository erzeugen. Das erledigt der folgende Befehl – ausgeführt im obersten Verzeichnis der Arbeitskopie:

$ svn copy ^/hello/trunk ^/hello/branches/feature-cmake

switch

Anschließend stellen die beteiligten Entwickler die Arbeitskopie auf den Feature-Branch um. Dabei spielt es praktisch keine Rolle, in welchem Zustand sich die Arbeitskopien befinden. Lokale Änderungen werden mit dem folgenden Befehl (ausgeführt im obersten Verzeichnis der Arbeitskopie) einfach in die aktuellste Version des Branches übernommen:

$ svn switch ^/hello/branches/feature-cmake

Bei svn switch handelt es sich im Wesentlichen um eine allgemeinere Form von svn update. Das bedeutet insbesondere, dass dabei die gleiche Art von Konflikten wie beim Update auftreten können. Doch keine Panik: Ohne lokale Änderungen kann es zu keinen Konflikten kommen. Und selbst bei der obigen Kombination aus svn copy und svn switch treten nur solche Konflikte auf, die bei svn update auch aufgetreten wären.

merge

Die Entwicklung auf dem Feature-Branch verläuft fast genauso wie auf dem trunk. Zusätzlich muss man lediglich immer wieder die Änderungen des originären auf den Feature-Branch übernehmen – abhängig von dessen Entwicklungsgeschwindigkeit nach Möglichkeit mehrmals pro Tag. Solange sich der Feature-Branch nicht zu weit vom Original weg entwickelt, ist das sehr einfach. Die wesentliche Arbeit erledigen die beiden folgenden Befehle, ausgeführt im obersten Verzeichnis der Arbeitskopie:

$ svn status --show-updates # check if working copy is clean and up-to-date $ svn merge ^/hello/trunk

Danach überprüft man das Ergebnis mit der Entwicklungsumgebung der Wahl, löst gegebenenfalls aufgetretene Konflikte auf und übernimmt es mit einem Commit ins Repository. Subversion merkt sich dabei, welche Änderungen bereits übernommen wurden, so dass sie beim nächsten Lauf nicht mehr berücksichtigt werden. Kontrollieren lässt es sich wie folgt:

$ svn mergeinfo --show-revs merged ^/hello/trunk

Wichtig für Feature-Branches ist, dass alle Änderungen des originären Branches übernommen werden. Andernfalls könnten Änderungen bei der späteren Reintegration verloren gehen. Im Falle unlösbarer Konflikte beim Merge kann man Änderungen auch manuell übernehmen. In diesem Falle sollte man trotzdem die Meta-Daten mit dem folgenden Befehl für die fehlgeschlagene Revision anpassen:

$ svn merge -c 9782 --record-only ^/hello/trunk

reintegrate

Es gibt zwei Möglichkeiten, was mit den Änderungen des Feature-Branches passieren kann: Entweder sie werden auf den originären Branch übernommen oder sie werden verworfen. Ersteres wird Reintegration genannt. Das klingt kompliziert, ist aber sehr einfach: Im Wesentlichen wird der originäre durch den Feature-Branch ersetzt. Daher kommt es dabei auch zu keinerlei Komplikationen – vorausgesetzt man hat zuvor alle Änderungen wie oben beschrieben auf den Feature-Branch eingespielt.

$ svn status # check if working copy is clean $ svn switch ^/hello/trunk $ svn merge --reintegrate ^/hello/branches/feature-cmake

Es müssen lediglich die oben stehenden Befehle im obersten Verzeichnis der Arbeitskopie ausgeführt werden. Mann sollte nochmals mit der Entwicklungsumgebung der Wahl kontrollieren, ob alles wie erwartet ist und das Ergebnis schließlich mit einem Commit in das Repositoy übernehmen.

delete

Unabhängig davon, ob man die Änderungen des Feature-Branches mit der Reintegration übernimmt, oder ob man alle Änderungen verwirft: Abschließend sollte der Feature-Branch unbedingt logisch gelöscht werden. Denn in beiden Fällen ist er für die Weiterentwicklung ungeeignet.

$ svn delete ^/hello/branches/feature-cmake

Ein Befehl reicht aus. Die Historie im Repository bleibt dabei selbstverständlich erhalten, und der alte Stand kann im Zweifelsfall jederzeit wiederhergestellt werden.