Verteilte Verwaltung

Verteilte Verwaltung

6. Februar 2009 - Verteilte Versionskontrollsysteme gelten als Zukunft bei der Software-Entwicklung. Wir stellen drei populäre Open-Source-Lösungen vor und vergleichen sie mit CVS und SVN.
Artikel erschienen in IT Magazine 2009/02

Versionskontrollsysteme (VCS) spielen eine grosse Rolle bei der Entwicklung von Software und, vor allem im UNIX-Bereich, der Verwaltung von Software-Konfiguration. Eine entsprechend lange Tradition haben diese Werkzeuge, die mit SCCS (Source Code Control System), das wie sein Nachfolger RCS (Revision Control System) nur einzelne Dateien verwalten konnte, bereits in den ersten UNIX-Systemen ihren Anfang genommen hat. Das wohl bekannteste Werkzeug ist das RCS-basierende CVS (Concurrent Versions System), das Mitte der 1980er-Jahre erstmals Repositories über das Netzwerk bereitstellte. Limitierungen von CVS sowie die steigende Popularität von Open-Source-Projekten, an denen sich immer mehr Entwickler beteilig-ten, haben seither zu einer Vielzahl von Neuentwicklungen und neuen Konzepten geführt. Heutzutage kann man die VCS grob in zwei Gruppen aufteilen: zentrale und verteilte Revisionsverwaltungssysteme.


Zentrale Revisionsverwaltungssysteme basieren auf einem zentralen Server respektive Repository, der Dreh- und Angelpunkt des jeweiligen Projekts ist. Dies ist der Ansatz, wie er vor allem von CVS und dem Nachfolgeprojekt Subversion (SVN) verfolgt wird. Verteilte Revisionsverwaltungssysteme (kurz DRCS oder DVCS) verzichten auf dieses zentrale Repository. Statt dessen verfügt jeder Entwickler über ein (oder auch mehrere) persönliches Repository, welches er bei Bedarf mit anderen Entwicklern abgleichen kann. Damit existieren beliebig viele Versionszustände, welche zu einem beliebigen Zeitpunkt zusammengeführt werden können. Der Vorteil dieses Vorgehens liegt auf der Hand: Jeder Entwickler hat sein Repository immer dabei – auch offline – und kann es selbst verwalten, klonen, löschen – ganz wie es ihm gefällt. Er kann selbst entscheiden, welche Version er mit anderen Entwicklern teilen möchte und welche er für sich selbst behält und hat trotzdem eine Historie seiner Arbeit. Dies kann unter anderem Experimente fördern und die Entwicklung grösserer Änderungen einfacher machen.

In der Regel ist das Vorgehen bei einem neuen, mit einem DRCS verwalteten Projekt jenes, dass der Start durch das Anlegen eines neuen Repository erfolgt. Die Entwickler klonen sich dieses Repository und beginnen daran zu arbeiten. Je nach Projektmanagement synchronisieren die Benutzer ihre Repositories in regelmässigen Abständen mit denen von anderen Entwicklern. Dabei ist die Hierarchie nicht wichtig. Das heisst, dass ein Entwickler durchaus nur mit seinem Kollegen in derselben Firma synchronisiert und dieser dann sein Repository an eine höhere Instanz synchronisiert. Beim nächsten Mal kann dies durchaus auch andersrum sein oder es wird mit einem Dritten synchronisiert. Aber auch der klassische Ansatz des zentralen Repository, bei dem die Entwickler alle gegen eine zentrale Instanz synchronisieren, ist möglich. Der Nachteil eines DRCS ist der, dass es durch eine potenziell beliebige Organisation der Repositores schwer ist, den Überblick zu behalten. Es ist daher wichtig, einen definierten Weg zu haben, wie beispielsweise ein Release eines Projektes zustande kommt. Dass dies selbst bei grossen Projekten funktioniert (und sogar effektiver als ein zentrales Repository sein kann), beweist die Entwicklung des Linux-Kernels, bei der mit Git ein DRCS zum Einsatz kommt. Aber auch für den persönlichen Gebrauch oder für kleine Projekte kann ein DRCS eine sehr grosse Hilfe sein. Beispielsweise ist es praktisch, wenn man seine Arbeit offline mit nach Haus nehmen oder unterwegs im Zug oder Flugzeug arbeiten kann.


Aktuell existieren drei «grosse» freie DRCS, die in verschiedenen mehr oder weniger grossen oder wichtigen Projekten Anwendung finden: Git, Mercurial und Bazaar. Sie sind alle drei für die wichtigsten Plattformen verfügbar und werden teilweise auch von IDE unterstützt.


- Git: Git ist von Linus Torvalds zur Pflege des Linux-Kernels als Alternative zum damals eingesetzten proprietären Bitkeeper entwickelt worden, da die anderen Alternativen nicht Torvalds Wünschen entsprachen. Der Kern von Git ist in C geschrieben, andere Teile in Form von Bourne Shell Scripts. Letztere sind sehr oft ein Kritikpunkt an Git, da der Code schlecht dokumentiert und zu grossen Teilen unsauber programmiert ist. In früheren Versionen tat man gut daran, das Wrapper-Toolkit Cogito zu verwenden, welches dem Entwickler das Leben sehr vereinfachte, da die Befehle von Git recht unübersichtlich und komplex waren. Mittlerweile wird Cogito aber nicht mehr weiterentwickelt, da sich beim User Interface von Git sehr viel getan hat. Ausser dem Linux-Kernel verwenden noch andere namhafte Projekte wie Android oder X.Org Git als Versionsverwaltung.


- Mercurial (hg): Fast zur selben Zeit wie Git entstand Mercurial. Die Konzepte sind denen von Git sehr ähnlich und auch die Befehle ähneln sich. Mercurial ist in Python geschrieben und wird für namhafte Projekte wie OpenSolaris oder Mozilla eingesetzt.


- Bazaar (bzr): Das jüngste Werkzeug ist Bazaar. Bazaar wurde 2005 von Canonical (die Firma, die hinter Ubuntu steht) entwickelt und ist wie Mercurial in Python geschrieben. Auch Bazaar wird bei prominenten Projekten eingesetzt, beispielsweise MySQL und – selbstverständlich – Ubuntu.


Parallel zu den erwähnten drei DRCS existieren noch einige weitere, beispielsweise Darcs oder Monotone, die aber weniger verbreitet sind und darum nicht eingehend betrachtet werden.


Das Vorgehen ist bei allen drei hier vorgestellten DRCS prinzipiell dasselbe. Auch die Befehle ähneln sich stark wie die Möglichkeiten (neu anlegen, klonen, Zweige anlegen usw.), die die drei bieten. Die grundlegende Arbeitsweise soll am Beispiel von Git kurz demonstriert werden.


Ein eigenes, neues Git-Repository legt man an, indem man im Verzeichnis, dessen Dateien man pflegen möchte, zuerst ein neues, leeres Repository innerhalb des Verzeichnisses (Unterverzeichnis «.GIT») mittels $ git init initalisiert. $ git add . fügt alle Dateien im aktuellen Verzeichnis zum (noch) leeren Repository hinzu, bevor mit $ git commit der Check-in ausgeführt, also der erste versionierte Inhalt erstellt wird. Neue Dateien fügt man mit $ git add neue_datei andere_datei noch_eine_datei hinzu. Damit sind die Dateien zwar Git bekannt, aber noch nicht versioniert. Man muss nach getaner Arbeit immer ein $ git commit absetzen, damit der Zustand auch als Version abgespeichert wird. Nur abgespeicherte («committed») Zustände werden bei einem Klonen oder Synchronisieren an andere Repositories weitergegeben. Eine Übersicht über das, was man geändert hat, welche Dateien neu sind und was noch nicht committed ist, bekommt man mit dem Befehl $ git status. $ git log liefert eine Historie, $ git log -p gibt dazu auch noch die Differenzen für jeden Zustand mit aus.


Oft ist es sinnvoll, einen Zweig (Branch) seines Projektes anzulegen. Damit hat man beispielsweise die Möglichkeit, verschiedene Releases seiner Software zu verwalten. Jedes Release ist ein eigener Branch/Zweig. Man kann etwa zu einem beliebigen Zeitpunkt eine ältere Version auschecken, mit dieser arbeiten, Bugfixes einpflegen, wieder abspeichern und das Ergebnis als Bugfix für eine ältere Version seiner Software freigeben. Anschliessend springt man wieder zum Hauptentwicklungszweig zurück und setzt seine Entwicklung fort. $ git branch kunde_alpha legt als Beispiel einen neuen Zweig mit dem Namen «kunde_alpha» an. Der Befehl $ git branch gibt die Liste aller verfügbaren Zweige aus. Wenn man ein $ git checkout kunde_alpha ausführt, wechselt man in eben jenen Zweig. Nach den Änderungen wird ein $ git commit -a eingegeben, damit die Änderungen auch eingecheckt sind. Anschliessend springt man mit $ git checkout master wieder in den Hauptzweig zurück. Der Hauptzweig nennt sich übrigens immer «master» und ist immer vorhanden. Möchte man nun seinen neuen Zweig mit dem Hauptzweig verbinden, macht dies – ausgehend vom Branch «master» – der Befehl $ git merge kunde_alpha. Änderungen sind mit dem obligaten Check-in abzuspeichern.


Möchte man von einem bestehenden Projekt starten, ist der erste Schritt der, sich einen Klon zu erstellen:


$ git clone git://git.kernel.org/pub/scm/git/git.git


Mit obigem Befehl holt man sich das aktuelle Repository des Git-Projekts selbst. Nach einiger Zeit (abhängig von der Internetanbindung) erhält man ein Verzeichnis mit einer exakten Kopie des Ausgangs-Repository lokal auf Platte. Man arbeitet anschliessend wie gewohnt auf seinem lokalen Repository. Um nun sein Werk auch an das originale Repository zu schicken, dient der Befehl $ git push. Umgekehrt holt man sich die neuesten Änderungen mit $ git pull.


Eingecheckte Änderungen können, anstatt sie zu klonen, auch über sogenannte E-Mail-Bundles verschickt oder importiert werden. Bei den E-Mail-Bundles handelt es sich um spezielle Dateien, die den aktuellen Zustand und die Änderungen des Repository in komprimierter Form beinhalten und welche via E-Mail an Entwickler versandt werden können. Nebst Git beherrschen auch Mercurial und Bazaar E-Mail-Bundles.


Git hat im Gegensatz zu den anderen beiden Systemen einige Schwächen beim Abspeichern von Versionszuständen. Ein Repository kann deshalb mit der Zeit ineffizient werden und sich aufblähen. Darum ist es von Zeit zu Zeit angebracht, dieses mit dem Befehl $ git gc zu reorganisieren, packen und unnötige Dateien zu löschen.


Neben der Kernfunktionalität bieten die Systeme interessante Funktionen, die eher den fortgeschrittenen Anwender ansprechen dürften. Ein Beispiel sind sogenannte Bisects, die die Fehlersuche erleichtern können: Man sucht sich eine Revision, bei der eine bestimmte Funktion des Programms noch fehlerfrei funktioniert hat und die letzte, die nicht mehr funktioniert. Durch das Bisect wird eine Revision dazwischen angelegt, die man testen kann. Ist die erhaltene Revision fehlerfrei, markiert man sie als «gut», andernfalls wird sie als nicht funktional markiert und man erhält automatisch eine weitere Revision, die man wiederum testen kann. Auf diese Weise kommt man recht einfach auf die Code-Differenz, die das Problem verursacht.


Cherry Picking erlaubt es, nur bestimmte Änderungen/Patches auf ein anderes Repository zu übertragen. Mit Shelve (bei Git: stash) kann man sich noch nicht eingecheckte Änderungen auf einen Stack legen, im Repository mit einer anderen Version arbeiten und anschliessend den noch nicht eingecheckten Zustand wieder herstellen. Dies ist sehr praktisch, um zwischendurch schnell Änderungen an einer anderen Revision vorzunehmen, ohne die aktuelle Arbeit zu verlieren oder einchecken zu müssen. Weiter bieten die Systeme sogenannte Pre- und Post-Commit-Hooks an. Damit hat man die Möglichkeit, vor oder nach dem Einchecken bestimmte Aktionen automatisch ausführen zu lassen. Code lässt sich so beispielsweise auf Syntaxfehler überprüfen.


Nebst den vielen gezeigten Gemeinsamkeiten gibt es zwischen den vorgestellten Systemen natürlich auch Unterschiede.


Als einziger Vertreter bringt Mercurial einen eigenen Webserver mit. Über diesen kann man mit einem Webbrowser auf das Mercurial-Repository zugreifen. Das Webinterface ist recht übersichtlich und ziemlich mächtig. Allerdings sollte man achtgeben, da dieser Webserver keinerlei Zugriffsbeschränkungen kennt. Es ist also ein anonymer Webzugang zum Repository möglich, was nicht immer gewünscht ist. Bazaar verfügt im Gegenzug über eine Plug-in-Schnittstelle, mit der sich das System sehr einfach erweitern lässt. Aktuell sind ca. 20 Plug-ins für die verschiedensten Zwecke verfügbar.


Weitere Unterschiede findet man vor allem unter der Haube und bei der Verfügbarkeit von graphischen Werkzeugen. Git ist sehr Linux-lastig und so gibt es ausserhalb vom Linux/UNIX-Umfeld (qgit, gitk) kaum grafische Helferlein. Mercurial und Bazar haben mit TortoiseHG und TortoiseBzr ein bereits von CVS und SVN bekanntes Front-end für Windows-Benutzer. Für den Mac gibt es ein natives grafisches Front-end für Mercurial (MacMercurial). Manche IDEs unterstützen neben CVS oder SVN mittlerweile auch verschiedene DRCS. Eclipse unterstützt alle drei Systeme, NetBeans derzeit nur Mercurial. Support für Git ist immerhin in der Betaphase. Apples XCode unterstützt derzeit keines der dreien, sodass man auf externe Werkzeuge angewiesen ist. Unterstützung für Mercurial und Bazaar gibt es hingegen für Microsofts Visual Studio. In Sachen Projektmanagement und Bugtracking können beispielsweise Redmine oder das sehr populäre Trac mit allen drei Werkzeugen umgehen.


Wer sein Projekt hosten lassen will, wie dies Sourceforge für CVS oder Tigris für SVN ermöglicht, hat unter anderem die Wahl zwischen Launchpad für Bazaar, Github für Git oder Bitbucket für Mercurial.


Es bleibt letztendlich eine Geschmacksfrage, für welches Tool man sich entscheidet. Eine breite Benutzerbasis haben alle drei, stabil und ausgereift sind sie auch. Git ist mehr im Linux-Umfeld zuhause, Mercurial eher bei anderen Unizes wie Solaris/OpenSolaris und mit TortoiseHG und TortoiseBzr sind Mercurial und Bazaar auch für Windows-Benutzer interessant. So ist es also tatsächlich nicht leicht, das System seiner Wahl auszusuchen. Vielleicht hilft ja die tabellarische Übersicht auf Seite 47, die die Systeme untereinander und zusätzlich mit CVS und SVN vergleicht.

Gregor Longariva ist Solaris-Administrator am Rechenzentrum der Universität Erlangen-Nürnberg.

Neuen Kommentar erfassen

Anti-Spam-Frage Vor wem mussten die sieben Geisslein aufpassen?
Antwort
Name
E-Mail
SPONSOREN & PARTNER