Kapitel 1. Versionskontrolle mit Subversion

Inhaltsverzeichnis

Vorteile der Versionskontrolle
Voraussetzungen
Beispiel
Weitere SVN-Kommandos
Gemeinsames Arbeiten
Upstream-Updates und neue Pakete
Abschließende Tipps
Dokumentation
Alternativen

Zusammenfassung

Der Einsatz von Subversion zur Pflege der eigenen Pakete und zur kollaborativen Entwicklung wird vorgestellt.

Vorteile der Versionskontrolle

Ein Versionskontrollsystem zu verwenden, hat eine Reihe von Vorteilen. So speichert es alle Versionsstände der Vergangenheit in einer effizienten Art und Weise. Mit Hilfe von Tags können einzelne Versionen noch einmal mit einem frei wählbaren Begriff besonders gekennzeichnet werden. Unterschiede zwischen verschiedenen Versionen können leicht dargestellt werden und man kann jederzeit zu älteren Versionen zurückkehren, wenn man sich vertan hat. Mittels branching ist die Pflege von beispielsweise experimentellen Parallelversionen möglich.

Benutzt man ein zentrales Repository, so hat man vollen Zugriff von jedem beliebigen Rechner aus und das wiederum ermöglicht eine kollaborative Entwicklung im Team. Subversion verringert mögliche Konflikte und vermeidet Datenverlust, in dem es fremde Änderungen nicht einfach überschreibt, sondern weitgehend automatisch zusammenführt.

Es gibt eine Reihe von verschiedenen Versionskontrollsystemen, welche wahrscheinlich alle mehr oder weniger für Debianpakete geeignet sind. Ich werde mich auf Subversion beschränken, dem Nachfolger von CVS, weil es leicht erlernbar und weit verbreitet ist. Es gibt viel Dokumentation dafür sowie eine Anzahl grafischer Frontends.

Voraussetzungen

Beispiel 1.1. Voraussetzungen für die Nutzung von Subversion

$ sudo apt-get install build-essential devscripts fakeroot meld svn-buildpackage
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut... Fertig
...
$ sudoedit /etc/apt/sources.list
$ sudo apt-get update
...
Es wurden 11,8kB in 2s geholt (5247B/s)
Paketlisten werden gelesen... Fertig


Zunächst müssen einige Pakete installiert werden. Weiterhin sollte ein Quelle für Sourcepakete in /etc/apt/sources.list in folgender Form vorhanden sein:

deb-src http://ftp.de.debian.org/debian unstable main contrib non-free

Und zum Schluss sollte noch einmal die apt-Datenbank aktualisiert werden.

Beispiel

Beispiel 1.2. Beispiel für die Nutzung von Subversion

$ svnadmin create ~/svnroot
$ export SVN=file://$HOME/svnroot
$ svn-inject -o -c0 acpid_1.0.4-7.1.dsc $SVN
...
Übertrage Daten ................
Revision 4 übertragen.
Done!
Removing tempdir /tmp/tmp.epQdN12567.
$ svn list $SVN
acpid/
$ svn list $SVN/acpid
branches/
tags/
trunk/
$ svn checkout $SVN/acpid/trunk acpid
A    acpid/acpi_listen.8
A    acpid/acpid.c
A    acpid/ud_socket.c
...
Ausgecheckt, Revision 4.
$ cd acpid
$ sensible-editor debian/README.debian
$ debchange -i
$ meld .
$ sudo apt-get build-dep acpid
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut... Fertig
0 aktualisiert, 0 neu installiert, 0 zu entfernen und 0 nicht aktualisiert.
$ svn-buildpackage --svn-ignore
Imported config directives:
        --svn-builder=debuild -uc -us
        --svn-no-links
...
Binary package:
 /home/twerner/build-area/acpid_1.0.4-7.2_i386.deb
rm -rf /home/twerner/build-area/acpid-1.0.4
$ svn status
M      debian/changelog
M      debian/README.debian
$ svn commit
Sende          debian/README.debian
Sende          debian/changelog
Übertrage Daten ..
Revision 5 übertragen.
$ svn-buildpackage --svn-tag
...
svn -m [svn-buildpackage] Tagging acpid (1.0.4-7.2) cp file:///home/twerner/svnroot/acpid/trunk file:///home/twerner/svnroot/acpid/tags/1.0.4-7.2

Revision 6 übertragen.
dch -D UNRELEASED -i NOT RELEASED YET

I: Done! Created the next changelog entry, please commit later or revert.
rm -rf /home/twerner/build-area/acpid-1.0.4


Für einen Test brauchen wird ein SVN-Repository, welches sich unter einer URL ansprechen, für die wir gleich eine Variable in ~/.bashrc definieren. Wer mehrere Repositories nutzt, muss dafür verschiedene Variablen definieren.

Im folgenden werden wir mit dem Paket acpid arbeiten, welches wir zunächst in Quellform herunterladen: http://debianpaket.de/acpid/acpid_1.0.4.orig.tar.gz, http://debianpaket.de/acpid/acpid_1.0.4-7.1.diff.gz sowie http://debianpaket.de/acpid/acpid_1.0.4-7.1.dsc und dann ins Repository importieren. Dann sehen wir, dass es im Repository ein Verzeichnis acpid gibt, das wiederum 3 Unterverzeichnisse trunk, tags und branches hat, wobei trunk den Inhalt des Debianpakets enthält, den wir gleich auschecken. Der Befehl wäre übrigens auch automatisch von svn-inject aufgerufen wurden, wenn es ohne -c0 aufgerufen wird.

Das neue lokale Verzeichnis acpid enthält nun alle Dateien, die durch acpid_1.0.4-7.1.diff.gz hinzugefügt oder geändert werden. Unveränderte Dateien aus acpid_1.0.4.orig.tar.gz wurden aufgrund der Option -o nicht zum Repository hinzugefügt. Nun ändern wir die Datei debian/README, fügen einen changelog-Eintrag hinzu und schauen uns die Änderungen an. Dann installieren wir die Build-Depends und bauen das Paket. Die Option --svn-ignore ist notwendig, weil wir lokale Änderungen noch nicht wieder eingecheckt haben, was wir auch mit sehen. Das Paket wird im Verzeichnis ../build-area gebaut und das Ergebnis ist dort zu finden, was den Vorteil hat, dass keine generierten Dateien im Arbeitsverzeichnis zurück bleiben. Sobald wir damit zufrieden sind, können wir die Änderungen committen wobei ein Editor startet, in dem man eine Logmeldung eintragen sollte. Schließlich taggen wir die Version noch mittels oder, wenn wir uns den erneuten Build sparen wollen, ergänzen wir --svn-tag-only. In diesem Zusammenhang gibt es noch die Option --svn-retag, falls wir einen versehentlich falsch gesetzten Tag überschreiben wollen.

Mit Meld kann man sich bequem die lokalen Änderungen noch einmal anschauen, bevor man sie ins Repository eincheckt.

Weitere SVN-Kommandos

Neue Dateien und Verzeichnisse muss man mit

svn add

erst bekannt machen, ansonsten werden sie von svn-buildpackage komplett ignoriert. Für Verzeichnisse gibt es noch das Kommando

svn mkdir

welches sowohl das Verzeichnis lokal erstellt als auch mit automatisch registriert.

svn remove

entfernt Dateien sowohl aus dem Dateisystem als auch aus Subversion.

svn copy

und

svn move

sind Varianten von add und rm unter Erhalt der bereits vorhandenen Versionsgeschichte; copy wird u.a. zum Taggen und Branchen eingesetzt.

svn revert

verwirft alle lokalen und noch nicht eingecheckten Änderungen an einer Datei und mit der Option -R auch rekursiv für ganze Verzeichnisbäume.

Eine Besonderheit von Subversion sind die Properties, also Metadaten für Dateien und Verzeichnisse. Mit

svn propset svn:executable debian/rules '*'

markiert man debian/rules als ausführbar, die Umkehrung ist

svn propdel svn:executable debian/control

Mit

svn propedit svn:ignore

kann man im Editor Patterns für zu ignorierende Dateien z.B. Backups eingeben. svn-inject -o setzt die Property mergeWithUpstream auf den Wert 1 für das Verzeichnis debian, um anzuzeigen, dass unmodifizierte Upstreamdateien nicht in SVN eingecheckt wurden.

Gemeinsames Arbeiten

svn status --show-updates

zeigt an, ob jemand anderes einen commit durchgeführt hat und welche Dateien geändert wurden. Die konkreten Änderungen kann man sich mittels

svn diff --revision HEAD

anschauen und mit

svn update

lokal einspielen. Letzteres ist unbedingt notwendig, bevor man selbst wieder committen kann. svn update versucht, eventuelle eigene Änderungen mit Änderungen anderer zu mergen. Selten auftretende Konflikte muss man aber von Hand lösen.

Upstream-Updates und neue Pakete

Zunächst laden wir eine neue Upstream-Version herunter: http://debianpaket.de/acpid/acpid-1.0.6.tar.gz und das Upgrade wird mit svn-upgrade durchgeführt wie im folgendem Beispiel. Unter Umständen kann es hier zu Konflikten kommen, die man manuell auflösen muss.

Beispiel 1.3. Upstream-Updates

$ svn-upgrade ../acpid-1.0.6.tar.gz
...
debchange -D UNRELEASED -v "1.0.6-1" "(NOT RELEASED YET) New upstream release"
Done! Last commit pending, please execute manually.
Process ended with code 0
$ svn diff
Index: debian/changelog
===================================================================
--- debian/changelog    (Revision 5)
+++ debian/changelog    (Arbeitskopie)
@@ -1,3 +1,9 @@
+acpid (1.0.6-1) UNRELEASED; urgency=low
+
+  * (NOT RELEASED YET) New upstream release
+
+ -- Torsten Werner <twerner@debian.org>  Sat, 15 Sep 2007 21:15:23 +0200
+
 acpid (1.0.4-7.2) unstable; urgency=low

   * test
  


Komplett neue Pakete beginnt man am einfachsten zunächst ohne SVN und importiert sie später mit

svn-inject -o

In späteren Kapiteln werden eleganter Methoden vorgestellt, die aber weitere Änderungen am Paket voraussetzen.

Abschließende Tipps

Pakete, die in einem SVN-Repository gepflegt werden, sollten um 2 Header im Sourcebereich von debian/control erweitert werden: Vcs-Svn und Vcs-Browser, wobei letztere Variable eine URL sein soll, die im Webbrowser aufgerufen werden kann. Im folgenden Beispiel wird ein Paket verwendet, welches im Gegensatz zu acpid tatsächlich Subversion einsetzt.

Beispiel 1.4. Vcs-Header in debian/control

Vcs-Svn: svn+ssh://svn.debian.org/svn/collab-maint/deb-maint/afbackup/trunk
Vcs-Browser: http://svn.debian.org/wsvn/collab-maint/deb-maint/afbackup/trunk


Weitere Optionen, die svn-buildpackage nicht kennt, gibt es einfach an das Buildkommando weiter, z.B. -S, welches nur ein Quellpaket und keine Binärpakete baut. Das Tool ist über einen Datei ~/.svn-buildpackage.conf konfigurierbar:

Beispiel 1.5. Konfiguration für svn-buildpackage

svn-builder=debuild -uc -us
svn-no-links
svn-dont-clean


In diesem Fall wird debuild zum Bauen aufgerufen, ohne zu signieren, es wird keine Optimierung über hard links durchgeführt und wird das clean target nicht separat aufgerufen, weil das bereits debuild übernimmt. Eine Alternative dazu ist die Konfiguration über SVN-Properties. Gelegentlich braucht man nicht nur den Inhalt des Debian-Diffs sondern des kompletten Pakets in ausgepackter Form. Mit

svn-buildpackage --svn-export

wird das Paket komplett in ../build-area ausgepackt.

Dokumentation

Das Buch "Version Control with Subversion" gibt es unter http://svnbook.red-bean.com. Dokumentation zu svn-buildpackage gibt es unter /usr/share/doc/svn-buildpackage/HOWTO.html/index.html und online unter http://debianpaket.de/svn-buildpackage/index.html.

Alternativen

Gegenüber seinem Vorgänger CVS cached SVN mehr Daten lokal und funktioniert damit besser offline. Außerdem beherrscht es atomare commits und erleichtert branching und merging. Für echte verteilte Versionskontrolle sind andere Systeme besser geeignet wie beispielsweise SVK (eine Erweiterung von SVN), arch/bazaar (von Ubuntu verwendet) oder git, was in einem späteren Artikel vorgestellt wird. Es gibt eine Reihe von grafischen Frontends wie svn-workbench, subcommander, kdesvn, subclipse und meld. Meld stellt Diffs wie im folgendes Bildschirmfoto sehr übersichtlich dar und beherrscht die grundlegenden SVN-Kommandos. Allerdings ist es kein vollwertiger SVN-Client, da bietet beispielsweise kdesvn mehr.