![]() |
|
URL dieses Artikels:
zu Ausgabe:
05.2003
Totale Kontrolle
Versionsmanagement mit subversion
von Susanne Schmidt
Software-Entwicklung ohne Versionsmanagement ist eine organisatorische Qual. Entwickler müssten sich Sourcen hin- und hermailen, selbst dafür sorgen, dass immer die richtigen Änderungen eingefügt werden und wenn dann drei Entwickler das gleiche Projekt bearbeiten, ist das Chaos vorprogrammiert. Für Ordnung im Chaos sorgt ein Versionsmanagement: subversion ist die aktuelle Fortentwicklung der Klassiker.
Ein Vorfahre von Versionsmanagement-Programmen ist RCS - das Revision Control System. Auf dieser Basis entwickelte sich CVS - das Concurrent Versioning System mit vielen Verbesserungen, um Entwicklern die Arbeit zu erleichtern. CVS ist von Anwendern sehr einfach zu bedienen; selbst ein Einsteiger versteht binnen Minuten, was cvs update und cvs commit bewirkt - um den Rest kümmert sich die Software selbst. Der Erfolg - aber vor allen Dingen die Grenzen von CVS - hat zur Implementation von subversion geführt. Subversion wird mit seiner Fertigstellung verschiedene Schönheitsfehler von CVS beheben: Es soll Binaries ordentlich verwalten, Dateien, Verzeichnisse und symbolische Links werden der Versionskontrolle unterliegen. Von vielen Entwicklern benötigt, sollen wichtige Aktionen wie move bei Fertigstellung funktionieren. Ganz fertig gestellt ist subversion noch nicht - viele Features befinden sich noch in der Implementation. Trotzdem funktioniert subversion heute gut genug, um ein paar neugierige Blicke darauf zu werfen. Installation Die Installation von subversion ist nicht schwierig: Für den Single-User Modus braucht man nur subversion, Berkeley-DB 4.x, den XML-Parser Expat und ein installiertes Python 2.x. und kann die Netzwerkkomponenten einfach weglassen. Für ein netzwerktaugliches subversion braucht man ein paar Komponenten mehr: Die Sourcen von Apache 2, die Neon-Library für WebDAV und die OpenSSL-Bibliotheken, um eine verschlüsselte Übertragung zu gewährleisten. Apache 2 übernimmt mittels HTTP 1.1 die Arbeit des Transports der Daten übers Netz. WebDAV erledigt später bestimmte Zugriffe auf das Repository. subversion, WebDAV und OpenSSL lädt der Apache automatisch. Sowohl für den Netzwerkbetrieb als auch lokal benötigt man Berkeley-DB als Backend zur Aufbewahrung der verwalteten Daten. Durch die Delegierung der Netzwerkfähigkeit an Apache fallen bei subversion Arbeitsweisen wie der pserver unter CVS weg. Das Anmelden am subversion-Server funktioniert über htaccess-Passworte und andere Mechanismen, die der Apache beherrscht. Für den Administrator bedeutet dies natürlich, dass er sich mit grundlegenden Verwaltungsarbeiten am Apache vertraut machen muss. Wer sich mit Apache und WebDAV gar nicht anfreunden kann, erhält in den Sourcen von subversion übrigens auch einen kleinen subversion-Server svnserve, der als Dämon läuft. Die Installation für den lokalen Modus ohne Netz - gut geeignet für erste Tests - erfordert zuerst die Installation von Berkeley-DB und Expat. Beide sind voneinander unabhängig und lassen sich leicht mit configure, make, make install installieren. Wer kein Python 2.x hat, braucht dies auch nur für den Buildvorgang - man muss also nicht erst das neue Python gegen Expat und Berkeley-DB linken. Nach dem Auspacken der Sourcen von subversion ruft man ./configure --with-berkeley-db=/pfad/zu/db4 auf.Danach folgt das übliche make und make install - wer will, kann noch ein make check für ein paar Tests durchlaufen lassen. In einigen Tutorials werden subversion, Berkeley-DB und der neue Apache mit Prefixen versehen, die die Binaries von Apache und subversion später in einem Verzeichnis (z.B. /usr/local/subversion/) vorhalten. Notwendig ist das nicht - wer den Apache 2 oder Berkeley-DB sowieso installiert hat, muss subversions configure die korrekten Prefixes seines Systems mitteilen. Viele Distributionen haben eine ältere Berkeley-DB vorinstalliert - kompiliert man die falsche Version ein, meldet subversion später einen Fehler wie svnadmin create SVNEin subversion im Netz benötigt Apache 2 mit WebDAV-Modul, OpenSSL mit der Neon-Bibliothek und natürlich auch Berkeley-DB, Expat und die Sourcen von subversion. Wenn Berkeley-DB schon für den clientseitigen Betrieb installiert ist, kompiliert man als nächstes die Neon-Bibliothek für WebDAV. Neon installiert man nach Expat, weil Neon Expat oder libxml als XML-Parser erwartet. Hier genügt ein configure, make, make install. Danach folgt der Apache mit einer längeren configure-Option: ./configure --enable-dav \ --enable-so \ --with-dbm=db4 \ --with-berkeley-db=/pfad/zu/berkeleydb4Zum Schluss kompiliert man subversion; diesmal mit den passenden Flags für den Apache-gestützten Netzwerkbetrieb: ./configure --with-berkeley-db=/pfad/zu/db4 \ --with-apxs=/apachepfad/bin/apxsFür OpenSSL-Support ruft man bei Neon, Apache und subversion den Schalter --with-ssl bzw. --enable-ssl auf. Danach muss der Apache für subversion konfiguriert werden, indem man in der http.conf das Verzeichnis für das Repository einträgt: <Location /SVN>Diese Direktive teilt Apache mit, dass Anfragen mit dem Pfad SVN vom DAV-Handler svn bearbeitet werden und auf dem physikalischen Verzeichnis /var/SVN arbeiten. Man ruft später nicht den ganzen Pfad zum Repository auf, sondern bloß http://subversionserver.de/SVN/ - der Apache versteht durch diese Direktive, dass SVN auf /var/SVN/ umgesetzt wird. Die Rechte für den Apache-Zugriff nicht vergessen! ![]() Abb. 1: Im Logfile von Apache 2 sieht man, was WebDAV wirklich tut. Svnserve als Alternative zum Apache wird einfach mit svnserver -d gestartet. Der Server nimmt dann Requests mit svn://localhost/repository/project an und kann vom Benutzer in ~/.subversion/servers außerdem noch für ssh-Zugriff konfiguriert werden. Trunk, Branch, Tag - Grundbegriffe in subversion Die Grundbegriffe von subversion kennen die meisten Benutzer bereits aus der CVS-Welt: Das Repository ist die komplette Datenstruktur, die in CVS als Dateien und Verzeichnisse auf der Festplatte gehalten wird. In subversion erledigt dies Berkeley-DB. Ein Projekt ist eine Unterstruktur innerhalb eines Repositorys - ganz banal das entsprechende (versionierte!) Verzeichnis. Verzeichnisse mit besonderen Eigenschaften (Properties - dazu später mehr) sind Module: Zu einem Modul kann man mehrere Unterverzeichnisse aus mehreren Repositories zusammenfassen. Das Versioning vollzieht sich immer bezogen auf ein Repository - deswegen kann es bei vielen Projekten sinnvoll sein, auch mehrere Repositorys anzulegen. Als Trunk bezeichnet man den Hauptbaum eines Projekts und als Branch einen Nebenzweig. Ein Branch ist bei subversion eine Kopie des Trunks. Es handelt sich dabei nicht um eine echte, verdoppelnde Kopie, sondern um eine Art Hardlink: Trunk und Branch sind nur einmal in der Berkley-DB vorhanden, werden aber ab der Abzweigung (seit dem Branch) getrennt bearbeitet und verwaltet. Natürlich kann ein Branch (oder mehrere) wieder zurück in einen Trunk migriert werden: Mittels eines Merges fügt subversion Änderungen verschiedener Branches über einen bestimmten Revisionsraum zusammen. Ein Revisionsraum kann eine Angabe wie von Revision 352 - Revision 763 oder die Änderungen seit April 2002 sein - subversion akzeptiert genau wie CVS bei vielen Befehlen sehr flexible Datums- und Versionsangaben. Ist man mit den Änderungen und Migrationen zufrieden und hat eine lauffähige Version, kann man einen Tag setzen: Damit wird ein bestimmter Zustand eines Projekts markiert. Der Tag ist im Grunde nur das Erzeugen eines Branches, mit dem man unterschiedliche Revisionen von Dateien und Verzeichnissen als zu einem Tag gehörig deklariert: Man kann damit wie über ein Alias arbeiten, z.B. release-0.7-stable auschecken oder als Archiv packen. Erste Schritte: subversion als Anwender Wenn alles installiert ist, experimentiert man am Besten lokal mit dem ersten Archiv: Mit svnadmin create SVN ist das erste Repository erstellt. Wirft man einen Blick hinein, finden sich ein paar ungewohnte Unterverzeichnisse: README conf/ dav/ db/ format hooks/ locks/ - in /db findet sich in Form von Berkeley-DB Dateien das Repository. In diesen Verzeichnissen editiert normalerweise nur der Administrator des Repositorys; der Anwender hat - genau wie bei CVS - nach dem Auschecken eines Projekts oder Moduls sein eigenes .svn/ in jedem Verzeichnis der lokalen Arbeitskopie. Subversions Befehlssyntax ist allgemein svn command options targetAlle möglichen Kommandos zeigt svn --help an; alle möglichen Optionen für ein Kommando sieht man mit svn help command. Mit svn import file:////home/user/SVN /home/user/TheProject MyProjectholt man sich das unverwaltete TheProject als Quelle ins Repository unter dem Zielnamen MyProject. Die Syntax von svn ist immer URI- bzw. URL-basiert: Um ein lokales Projekt in einen entfernten subversion-Server zu importieren, gibt man einfach svn import http://subversionserver.de/SVN/ /home/user/TheProject MyProject an.Subversion legt dann auf dem Server im Repository das neue Projekt MyProject an und importiert alles aus /home/user/TheProject/ dorthin. Jetzt arbeitet man wie unter CVS gewohnt. Mit svn checkout file:///home/user/SVN/MyProject MyCopycheckt man sich lokal ein Projekt (oder Modul) als Arbeitskopie ins Verzeichnis MyCopy aus; mit svn checkout http://subversionserver.de/SVN/MyProject MyCopyholt man das gleiche von einem entfernten Server. Dank WebDAV ist via HTTP keine absolute Pfadangabe nötig. Während man mit svn arbeitet, fällt die Vertrautheit mit den üblichen CVS-Befehlen angenehm auf: svn update aktualisiert die lokale Arbeitskopie und mit svn commit checkt man eigene Änderungen ins Repository ein. ![]() Abb. 2: Dank der Zusammenarbeit mit Apache gibt es ein kleines Web-SVN gleich dazu. Erst vergewissern - dann ändern Bevor man Änderungen einpflegt, zeigen svn status und svn diff Änderungswünsche an, ohne sie durchzuführen. svn diff, svn status und svn revert können dank des Caching-Systems von subversion auch ohne Netzwerkverbindung arbeiten: Die betreffenden Änderungen werden in den Metadaten in ~/.svn vorgehalten, bevor alles an den Server beim svn commit gesendet wird. Diese Metadaten sind XML-Files, in denen die Eigenschaften, Dateilisten, Namen, Autor, Checksumme, Timestamps und vieles mehr festgehalten werden. Wer neugierig ist, kann die Metadaten in ~/.svn im Klartext angucken. Svn status zeigt an, welche Änderungen der Datei anstehen: ein --verbose (-v) ergänzt die Revisionsnummer, wer die Änderungen gemacht hat und in welcher Revision die letzte Änderung stattfand. Kombiniert man --verbose noch mit --show-updates (-u) markiert subversion die Dateien, die beim Update bearbeitet werden. Für -u braucht man wieder eine Verbindung zum Repository: -u vergleicht die Arbeitskopie mit der Repository-Version der Dateien. Ein typischer Output sieht dann wie folgt aus: 4 4 banshee .A(dded), D(elete), M(odified), (Mer)G(ed), U(pdate), C(onflict) zeigen in den ersten beiden Spalten den Status der Datei und der Eigenschaften separat an. Das * erscheint, wenn im Repository neuere Dateien liegen als in der Arbeitskopie. Die Revisionen der Arbeitskopie und der Commits werden aufgelistet als Ziffern, dann folgt der Name desjenigen, von dem der letzte Commit stammte. Natürlich gibt es auch svn diff - um sich die Unterschiede zwischen lokaler Kopie und der entsprechenden Datei im Repository anzeigen zu lassen oder um Patch-Files zu erstellen. Ein einfaches svn diff > mypatch genügt, um einen Patch zu erstellen. Subversions diff arbeitet bereits mit unified diff: Durch die Angabe von Zeilennummern, - und + versteht patch, welche Zeilen gelöscht und welche hinzugefügt werden sollen. Stellt man beim Blick in den Status oder ins Diff fest, dass man Fehler gemacht hat, hilft svn revert weiter: Damit werden Änderungen der lokalen Arbeitskopie wieder zurückgenommen. Mit verschiedenen Parametern kann svn noch filigraner Nachrichten anzeigen oder Diffs erstellen: Die Option -r wird von list (Verzeichnisse unter Versionskontrolle auflisten), cat (Datei anzeigen), log und diff verstanden und zeigt Mitteilungen einer bestimmten Revision: svn log -r4 zeigt beispielweise nur die Logmessages von Revision 4 an. svn diff -r3:4 http://subversionserver.de/SVN/source.c > mypatchwürde aus Revision 3 und 4 ein Diff erstellen und es in ein Patchfile umleiten. Der Schalter -r versteht Angaben wie: 22:55 - Revisionsnummer 22 bis 55, oder 10:{today} - von Revision 10 bis zum Datum von heute. HEAD kennzeichnet mit -r2:HEAD alle Revisionen von Nummer 2 bis zur letzten aktuellen Revision. Ein svn cat -r7 foobar.c > foobar.cleitet den Inhalt von foobar.c, Revision 7, in eine neue Datei um - sehr bequem, um alte Versionen zu restaurieren. Mit Branches und Mergers arbeiten Um in einem Projekt über mehrere Monate hinweg mit unstabilen Sourcen arbeiten zu können oder größere Projektumstellungen zu bewältigen, braucht man früher oder später einen Branch (Zweig) des Hauptprojekts. Mit subversion erledigt man das mit svn copy http://subversionserver.de/SVN/trunks/projectA \ http://subversionserver.de/SVN/branches/projectA-branchIst der Branch kopiert, checkt man sich die Kopie mit svn checkout http://subversionserver.de/SVN/branches/projectA-branch MyBranchneu aus und arbeitet darin wie gewohnt weiter. Jetzt existieren virtuell zwei Projekte, die sich beim Bearbeiten nicht ins Gehege kommen. Interessant wird es, wenn man einen Branch wieder zurück in den Trunk, also ins Ursprungsprojekt einfügen will: Mit svn merge kann man das bequem (wenn auch meistens nicht konfliktfrei) erledigen. svn merge ist eine Schwester von diff: statt ein Diff vom Branch zu erstellen und den Patch dann auf den Trunk anzuwenden, erledigt svn merge dies in einem Rutsch. merge versteht genau wie diff auch den Parameter -r, um ganz bestimmte Revisionen für einen Merger auszuwählen. merge hat ein paar Fähigkeiten mehr als ein normaler Patch: bewegte Verzeichnisse, Namensänderungen oder kopierte Files erkennt svn merge und fügt diese Veränderungen mit ein. In der Theorie klingt das natürlich toll - in der Realität dürften viele Konflikte zwischen Änderungen auftreten. Files, die mit C für Conflicts markiert sind, müssen geordnet und bearbeitet werden, bis der Konflikt aufgelöst ist. Subversion legt dafür diverse Temp-Files mit speziellen Markierungen in der Arbeitskopie des Users an. Nach der Konfliktbehebung räumt ein svn resolve die Markierungen der Konflikte sauber wieder weg. Liegen bereits viele Megabyte von Sourcen eines Projekts in der Arbeitskopie, kann man einen Branch davon ressourcenschonend erzeugen, indem man mit svn switch die aktuelle Arbeitskopie zu einer Arbeitskopie des Branches macht. Subversion ändert die Arbeitskopie in den Branch um - commitet man jetzt Änderungen, landen diese im Branch des Repositorys und nicht im ursprünglichen Trunk. Metadaten und Eigenschaften Die oben kurz erwähnten Metadaten in ~/.svn in jeder Arbeitskopie können übrigens vom Benutzer verwendet werden und unterliegen auch der Versionskontrolle - deswegen hat svn status zwei Spalten. Verschiedene Kommandos wie svn propset, propedit, prodel, proplist und propget können die Eigenschaften (Properties) bezogen auf jede einzelne Datei bearbeiten. Die Eigenschaften sind dabei frei wählbar und werden so vergeben: svn propset Autor "Susanne Schmidt" lyrik.cgisetzt die Eigenschaft Autor mit dem Wert Susanne Schmidt auf die Datei lyrik.cgi. svn proplist und proplist -v zeigen, welche Eigenschaften mit welchen Werten gesetzt sind. Sind die Eigenschaften bearbeitet, folgt der übliche commit. Ein Blick in ~/.svn/props/lyrik.cgi.svn-work zeigt die Änderungen dieser Datei. Alle subversion-Eigenschaften beginnen mit svn: - svn:executable, svn:eol-style, svn:keywords oder svn:ignore sind einige Eigenschaften, die subversion bearbeiten kann. Will man gezielt für ein Verzeichnis das Ignorieren von bestimmten Dateitypen - typischerweise Sicherheitskopien von Editoren, Objectfiles oder Logfiles von LateX - anschalten, ruft man einfach svn propset svn:ignore "~" Verzeichnis auf. Ein svn commit ignoriert die Dateien mit der Endung ~ jetzt - erst ein gezieltes svn add foobar~ fügt eine ignorierte Datei dem Repository hinzu. Wer aus CVS-Zeiten noch ein .cvsignore hat, kann dies ganz einfach als Pattern für ein svn:ignore verwenden: svn propset svn:ignore -F .cvsignore . setzt die Pattern aus dem File (-F) .cvsignore als subversion-Eigenschaft bezogen auf das aktuelle Verzeichnis. Die oben bereits erwähnten Module erzeugt man ebenfalls mit Eigenschaften: Man weist einem Verzeichnis mit der Eigenschaft svn:externals einfach eine Liste mit Verzeichnissen, Dateien und Repositories zu. Bei svn checkout, update und commit werden die svn:externals einfach über den Verzeichnisnamen des Moduls aufgelöst und bearbeitet. Als Administrator eines Projekts Die Administration von subversion unterscheidet sich natürlich grundlegend vom Gebrauch von subversion als Benutzer. Als Administrator kann man unterschiedlichste Anweisungen an subversion übergeben, die sich auf die Arbeit von Benutzern auswirken. subversion versteht Anweisungen - so genannte Hooks die vor einem Commit, beim Start eines Commits und nach einem Commit ausgeführt werden können. Das typische post-commit-Skript ist die Benachrichtung einer Mailingliste über Änderungen einer Datei inklusive ihrer commit-Messages. Ein klassisches pre-commit-Skript ist beispielsweise die Kontrolle über den Einrückungsstil der Sourcen oder die Verpflichtung, keine Funktion ohne Kommentar einzuchecken und dergleichen mehr. Natürlich kann man hier auch Tools wie indent verwenden und Einrückungen automatisch vornehmen lassen. Mit start-commit-Hooks kann man sogar benutzerspezifische Aktionen durchführen - je nachdem, wer gerade einen Commit ausführt. Ein Hook wird in einem Template-File (start-commit.tmpl) eingetragen, dass subversion in /hooks des Repository erwartet; das auszuführende Skript legt man mit passenden Rechten dazu. Im Source-Paket von subversion liegen mehrere fertige Hook-Skripte griffbereit. Als Administrator sind außerdem noch Befehle wie svnadmin dump, um ein Backup im dump-Format anzulegen oder svnadmin lock, um einzelne Teile des Repositorys gegen Schreibzugriff zu schützen, wichtig. Wer also subversion benutzen will, findet sich als CVS-User leicht in die Syntax ein; die Installation klappt problemlos und viele Features funktionieren bereits und der Gebrauch ist wirklich sehr einfach. Wer allerdings eine fertige Release erwartet, wird sich doch noch einige Zeit gedulden müssen - solange sollte man das vielversprechende Projekt nicht aus den Augen verlieren! Links
|
||
|