Apache Subversion: Release Branches

von Hubert Schmid vom 2012-12-02

Release Branches sind mit Apache Subversion eine ganz einfache Sache. Dennoch wird mir immer wieder berichtet, dass sich Entwickler schwer damit tun. Aus meiner Sicht ist das im Wesentlichen auf zwei Punkte zurückzuführen: Unstrukturierte Vorgehensweise und Verwendung ungeeigneter Werkzeuge. Die folgenden Abschnitte sollen zeigen, wie einfach es sein kann.

create

Einen Release-Branch legt man ganz einfach an, indem man einen der beiden folgenden Befehle in der Arbeitskopie ausführt. Dabei wird die Änderung direkt im Repository durchgeführt. Die beiden Alternativen unterscheiden sich nur durch die Angabe der sogenannten Revisionsnummer, wobei der zweite Befehl ermöglicht, bei Bedarf den Branch aus einer früheren Version des trunk zu erzeugen.

$ svn copy ^/hello/trunk ^/hello/branches/release-0.42 $ svn copy ^/hello/trunk@9744 ^/hello/branches/release-0.42

Man kann svn copy auch auf Verzeichnisse und Dateien in der Arbeitskopie anwenden. Branches sollte man auf diese Weise allerdings auf keinen Fall erzeugen. Falls Anpassungen auf dem neu erzeugten Branch notwendig sind, sollten diese stets getrennt von der Erzeugung durchgeführt werden.

checkout

Für Releases sollte man eine getrennte Arbeitskopie verwenden, um die Weiterentwicklung von der Arbeit an Releases zu entkoppeln. Ausgeführt im obersten Verzeichnis einer Arbeitskopie, legt der folgende Befehl eine entsprechende Arbeitskopie parallel zur Existierenden an.

$ svn checkout ^/hello/branches/release-0.42 ../hello-0.42

merge

Mit einem Merge kann man gezielt Änderungen eines Entwicklungszweigs auf einen anderen übernehmen. Ganz einfach ist es, wenn die Übernahme stets in der gleichen Richtung erfolgt: Vom trunk zum branch. Der Merge erfordert selbst nur einen Befehl aus dem obersten Verzeichnis der Arbeitskopie. Man sollte aber zuvor sicherstellen, dass keine lokalen Änderungen ausstehend sind, und dass man sich auf dem richtigen Entwicklungszweig in der aktuellsten Revision befindet.

$ svn status # check if working copy is clean $ svn switch ^/hello/branches/release-0.42 $ svn merge -c 9757 ^/hello/trunk

In den meisten Fällen kann Subversion die Änderungen automatisch auf den Code des Release adaptieren. Dann reicht es, mit der Entwicklungsumgebung der Wahl das Ergebnis zu kontrollieren, gegebenenfalls anzupassen und in der Repository zu übernehmen.

conflict

Wenn sich der Code zwischen trunk und branch zu weit auseinander entwickelt hat, dann treten beim Merge unlösbare Konflikte auf. In diesem Fall ist es meist einfacher, die Aktion rückgängig zu machen und die Änderung nochmals von Hand auf dem Release-Branch durchzuführen. Die folgenden Befehle stellen den ursprünglichen Zustand nach einem fehlgeschlagenen Merge wieder her. Gleichzeitig werden die Meta-Daten angepasst, um die Änderung dennoch als solche zu kennzeichnen.

$ svn revert -R . $ svn merge -c 9757 --record-only ^/hello/trunk

invert

In vielen Fällen findet man auf dem branch Fehler, die auch auf dem trunk noch nicht korrigiert sind. In diesen Fällen sollte man die Änderung stets zunächst auf dem trunk durchführen und anschließend wie oben beschrieben auf den branch übernehmen. Mit den folgenden beiden Befehlen – ausgeführt im obersten Verzeichnis der Arbeitskopie – wechselt man einfach und schnell auf den trunk in die aktuellste Revision.

$ svn status # check if working copy is clean $ svn switch ^/hello/trunk

Auf Basis der sauberen Arbeitskopie wird die Anpassung entwickelt und in das Repository übernommen. Anschließend überträgt man die Änderung wie oben beschrieben auf den Release-Branch.

info

Auch den ersten Blick sieht ein Branch in Subversion nur wie ein weiteres Verzeichnis aus. Tatsächlich erfasst die Versionsverwaltung hinter den Kulissen zahlreiche Informationen über die durchgeführten Aktionen. So lässt sich beispielsweise mit dem folgenden Befehl herausfinden, welche Änderungen des trunk bereits auf den branch übernommen wurden.

$ svn mergeinfo --show-revs merged ^/hello/trunk ^/hello/branches/release-0.42

Außerdem unterstützen zahlreiche Befehle die Option --use-merge-history, mit der die übliche Ausgabe um Informationen der originären Änderungen angereichert werden. Das gilt insbesondere für die folgenden beiden Befehle:

$ svn log -v --stop-on-copy --use-merge-history ^/hello/branches/release-0.42 $ svn blame --use-merge-history hello.cpp

delete

Zu guter Letzt sollte der Release-Branch gelöscht werden, sobald er nicht mehr benötigt wird. Dadurch ist transparent, welche Branches noch aktiv und relevant sind. Die Historie im Repository bleibt beim Löschen selbstverständlich erhalten, und der Branch könnte jederzeit im Zweifelsfall wiederbelebt werden.

$ svn delete ^/hello/branches/release-0.42