Medizinische Informatik Master (MIM)

Subversion (SVN)

Was ist das und wozu braucht man das?

Im Laufe der Arbeit mit Textdateien (wie Quelltexten zum Beispiel) kommt es immer wieder zu organisatorischen Problemen:

  • Code wird “verschlimmbessert”: Eine gut gemeinte Modifikation führt zu Fehlern, die es vorher nicht gab
  • In teambasierten Projekten ist nicht klar, wer die gerade aktuelle und richtige Version des Projektes besitzt
  • Mehrere Personen möchten (quasi) gleichzeitig an den selben Dateien arbeiten

Zentrale Versionskontrollsysteme nehmen sich dieser Probleme an und bieten passende Lösungen. Subversion (auch: “SVN”) ist ein solches System.

Das Prinzip der zentralen Versionskontrolle

Bei der zentralen Versionskontrolle gibt es einen Referenzort, an dem sich der aktuelle Stand (und die gesamte Historie) des Projektes befindet. Dieser Ort nennt sich “repository” (kurz: “repos” oder “repo”). Dieses repository befindet sich auf einem Server, zu dem jeder Projektbeteiligte Zugang hat. Das unter Versionskontrolle stehende Projekt besteht aus einem Verzeichnis. Alle darin enthaltenen Dateien und Ordner gehören zum selben repository und werden daher mit diesem Wurzelverzeichnis versioniert.

Zur Versionierung des repositorys nummeriert Subversion jede Änderung durch. Diese Nummern sind die sogenannten Revisionsnummern (kurz englisch: “revisions”). Jede Datei/Jedes Verzeichnis liegt in einer Revisionsnummer vor, die Nummern werden aber über das gesamte repository durchgezählt. Werden durch einen Mitarbeiter eine oder mehrere Dateien/Verzeichnisse verändert, zählt Subversion die Revisionsnummer der veränderten Dateien/Verzeichnisse und der darüber liegenden Verzeichnisse hoch. Dadurch hat das Wurzelverzeichnis immer die neueste Revisionsnummer. Zur Veranschaulichung ein kurzes Beispiel:

Das repository besteht aus einem Ordner namens “myProject”. In diesem Ordner befindet sich eine Datei “readme.txt” und ein Ordner “files”. Dieser Ordner enthält wiederum zwei Dateien “foo.txt” und “bar.txt”. Die Dateihierarchie sieht also wie folgt aus:

Die Zahl hinter den Dateien und Verzeichnissen ist die Revisionsnummer, in der die jeweilige Datei / das jeweilige Verzeichnis derzeit vorliegt. Das gesamte Projekt besitzt also die Revisionsnummer 11.

Ändert nun eine Person die Datei “foo.txt”, wird ihre Revisionsnummer um eins erhöht. Da die Datei in einem Ordner (“files”) liegt, wird auch dessen Revisionsnummer um eins erhöht. Auch dieser Ordner liegt in einem Verzeichnis (“myProject”), dessen Revisionsnummer wird also auch um eins erhöht. Das Ergebnis sieht dann wie folgt aus:

Die Datei “foo.txt” und die Ordner “files” und “myProject” haben also die Revisionsnummer 12, alle anderen Dateien/Ordner liegen noch in Revisionsnummer 11 vor. Da “myProject” auch das Wurzelverzeichnis des repositorys ist, liegt das gesamte Projekt in der Revisionsnummer 12 vor.

Damit zur Arbeit am Projekt keine dauerhafte direkte Verbindung zum repository vonnöten ist, lädt man sich mit passenden SVN-Kommandos (siehe “Die wichtigsten Befehle”) (“checkout”/”update”) den gewollten Stand des Projektes herunter. Normalerweise wählt man die höchste, also aktuelle Revisionsnummer. Diese Revisionsnummer wird auch “head revision” genannt. Die mit dem repository “verknüpfte” Kopie nennt sich “Arbeitskopie” oder englisch “working copy”. In dieser Arbeitskopie findet nun die Arbeit statt. Ist ein abgeschlossener Teil der Arbeit getan (ein Fehler behoben, der Arbeitstag beendet oder so), wird mit einem weiteren SVN-Kommando dem repository und damit allen anderen Beteiligten mitgeteilt (“commit”), dass Veränderungen vorgenommen wurden und eine neue Version des Projektes vorliegt. Alle Dateien und Ordner, die “commited” werden, sind damit im repository aktualisiert und für alle Beteiligten gültig. Man sollte also möglichst die Dateien und Ordner commiten, die im Rahmen der getanen Arbeit zusammen gehören. Denn falls etwas falsch gemacht wurde, können durch den Wechsel zur nächst kleineren Revisionsnummer die letzten Änderungen rückgängig gemacht werden.

Mit Hilfe der Revisionsnummern ermöglicht Subversion das Bearbeiten des Projektes von verschiedenen Personen im selben Zeitraum. Zum Verständnis des Verhaltens auch hier ein kleines Beispiel:

Zwei Projektmitarbeiter – Alice und Bob – laden sich die head revision des obigen Projektes “myProject” herunter. Die Arbeitskopien liegen also in der Revision 12 vor. Bob fügt der Datei “bar.txt” eine Zeile Text hinzu, Alice arbeitet an “foo.txt” weiter. Weil Bob ein wenig schneller ist, commitet er als erster seine Änderungen. Deswegen liegen “bar.txt”, “files” und “myProject” nun in Revision 13 vor. Danach teilt Alice ihre Änderungen mit. Da sie eine Datei bearbeitete, die nicht in der Zwischenzeit aktualisiert wurde, kann auch sie commiten. Deshalb ändern sich die Revisionsnummern wie folgt:

Das verteilte gleichzeitige Arbeiten hat problemlos funktioniert. Wenn Alice und Bob ihre Arbeitskopien aktualisieren (“update”), sind sie beide auf dem Stand des repositorys und können die Änderungen des anderen einsehen.

Was passiert aber, wenn beide – Alice und Bob – an der “readme.txt” gearbeitet haben? Ein Konflikt entsteht, der gelöst werden muss.

Konfliktmanagement

Wird eine Datei im selben Zeitraum von zwei verschiedenen Personen bearbeitet, laufen die commits Gefahr, sich gegenseitig zu überschreiben oder zu widersprechen. Dies wäre tragisch für die Teamarbeit und wird deshalb von Subversion gesondert behandelt. Zur Veranschaulichung bleiben wir bei dem obigen Beispiel:

Alice und Bob haben in ihrer Arbeitskopie die Datei “readme.txt” in der Revision 14 vorliegen und bearbeiten sie im selben Zeitraum. Bob ist wieder einmal schneller und kann seine Änderungen commiten. Die Datei hat nun die Revisionsnummer 15 (genauso wie “myProject”). Möchte nun Alice ihren commit fahren, teilt ihr das repository mit: “your file is out of date”. Ein anderer Mitarbeiter war also schneller und im repository liegt eine aktuellere Revision als die, auf der die Arbeitskopie von Alice beruht, vor. Alice wird also dazu aufgefordert, ihre Arbeitskopie zu aktualisieren (“update”). Dabei können folgende Situationen auftreten:

Die Datei wurde von Alice und Bob an zwei verschiedenen Stellen modifiziert (z.B. hat Bob die Einleitung, Alice ein spätes Kapitel der “readme.txt” bearbeitet)

Die Datei wurde von beiden an der selben Stelle modifiziert (beide haben im Impressum das Datum aktualisiert, Bob entschied sich aber für die englische, Alice für die deutsche Schreibweise)

Der erste Fall wird von Subversion automatisiert bearbeitet: Die aktuelle Revision aus dem repository und die Arbeitskopie werden zusammengeführt (“merge”). Subversion geht nämlich davon aus, dass Änderungen, die an verschiedenen Stellen statt fanden, sich inhaltlich nicht widersprechen (was bei Quelltexten nicht unbedingt der Fall ist, weshalb man das merge-Ergebnis durchaus überprüfen sollte).

Der zweite Fall ist ein sogenannter Konflikt. Subversion weiß nicht, welche Modifikation die “bessere” ist. Deshalb wird die Datei in einen Konflikt-Zustand versetzt. Dieser Zustand liegt aber nur in Alice’s Arbeitskopie vor. Das repository hat also einen gültigen Zustand, Alice’s Änderungen sind aber nicht darin enthalten. Nun liegt es an den beteiligten Personen, den Konflikt aufzulösen. Alice sollte sich also mit Bob in Verbindung setzen und mit ihm diskutieren, welches Datumsformat wohl das passendere für “readme.txt” ist. Zur Unterstützung der Bearbeitung des Konfliktes legt Subversion folgende Dateien an:

Zur ursprünglichen “readme.txt” sind also einige “Kopien” der Datei hinzugekommen. Dabei ist die Datei

  • readme.txt.r14 die Kopie der Datei zu dem Zeitpunkt, als sich Alice und Bob “noch einig waren”. Möchte man also keine von beiden Änderungen übernehmen, sollte man zu dieser Revision zurückkehren
  • readme.txt.mine die Kopie der Datei mit den Änderungen, die in der Arbeitskopie vorliegen, also von Alice gemacht wurden, bevor der Konflikt auftrat
  • readme.txt.r15 die Kopie der Datei, mit der die Arbeitskopie-Variante in Konflikt steht. Es ist also die head revision aus dem repository
  • readme.txt die im Konflikt stehende Datei mit passenden Konflikt-Markern

Möchte man die im Konflikt beteiligten Zeilen direkt vergleichen, sollte man “readme.txt” öffnen. Subversion hebt die entsprechenden Stellen dabei wie folgt vor:

Diese Bearbeitung wirkt zwar kompliziert, ermöglicht aber die direkte Darstellung beider Versionen beieinander. Den Blick für die Konfliktlösung entwickelt man schnell. Und noch besser: die üblichen Tools und PlugIns für Subversion (siehe “Tools für Subversion”) bieten verschiedene Darstellungen (farbliche Unterschiede, Gegenüberstellung rechts-links) an, um das Lösen von Konflikten zu vereinfachen.

Mit diesen Hilfestellungen wird es Alice und Bob gelingen, sich für eine Variante des Datums zu einigen. Zur Lösung des Konfliktes kann Alice dabei wie folgt vorgehen:

  • sie bearbeitet die Datei readme.txt, indem sie die Konfliktmarker stückweise entfernt und sich für eine Variante entscheidet
  • sie kopiert eine der anderen Dateien an Stelle der readme.txt
  • sie verwirft offiziell ihre Änderungen (“revert”) und akzeptiert damit die Revision des repositorys. Alle lokalen Änderungen in Alice’s Arbeitskopie seit dem letzten update gehen dadurch verloren

Wichtig für die ersten beiden Varianten ist, dass am Ende der Konfliktbearbeitung die Datei readme.txt der Version entspricht, auf die sich Alice und Bob geeinigt haben. Alice kann darauf hin den Konflikt als gelöst markieren (“resolve”). Subversion löscht darauf hin die für die Konfliktlösung erzeugten Dateien. Mit einem erneuten commit kann nun Alice diese Bearbeitungen mitteilen und somit im repository allen zugänglich machen.

(Anhand der Konfliktbearbeitung ist auch klar, warum Subversion vor allem für textbasierte Dateien gedacht ist: Unterschiede werden zeilenweise untersucht und im Konfliktfall mit passenden Markern hervorgehoben. Mit Binärdateien [Bilder, Musik] kann Subversion deswegen nicht so gut umgehen. Solche Dateien können natürlich auch versioniert werden. Haben aber zwei Personen die selbe Binärdatei bearbeitet, wird aber immer ein Konflikt auftreten. Diesen kann man auch nur lösen, indem man sich für eine Datei entscheidet.

Außerdem werden Subversion-Verzeichnisse, die Binärdateien enthalten, von Revision zu Revision ungemein größer. Subversion merkt sich nämlich von einer Revision zur nächsten bei Textdateien nur die Änderungen an diesen, was bei Binärdateien nicht möglich ist.)

Die wichtigsten Befehle

An tiefer in Subversion einsteigenden Stellen (siehe “Weiterführende Links”) werden die zur Verfügung stehenden Kommandos ausführlich beschrieben. Es folgt ein Auszug mit Kurzbeschreibung derer, die man kennen sollte, um mit Subversion zu arbeiten:

  • checkout: Lädt das repository (oder ein Unterverzeichnis dessen, je nach Wahl) in ein Verzeichnis des eigenen Rechners herunter. Der Download bildet automatisch die Arbeitskopie. Standardmäßig wird die head revision heruntergeladen, das Auswählen einer anderen Revision ist aber auch möglich.
  • update: Bringt Änderungen aus dem repository in die Arbeitskopie ein. Die Konsole gibt dabei für jede Datei an:
    • A: Hinzugefügt (“Added”)
    • D: Gelöscht (“Deleted”)
    • U: Aktualisiert (“Updated”)
    • C: Konflikt (“Conflicted”)
    • G: Zusammengeführt (“merGed”)
  • commit: Teilt dem repository (und damit allen Mitarbeitern) die Änderungen der eigenen Arbeitskopie mit und lädt diese hoch. Ein commit sollte immer mit einem aussagekräftigen Kommentar versehen werden!
  • resolve: Erklärt eine konfliktbehaftete Datei als gelöst. Von Subversion zur Konfliktlösung erzeugte Dateien werden gelöscht, ein commit für die “gelöste” Datei ist möglich.
  • revert: Widerruft alle Änderungen an einer Datei oder einem Verzeichnis.
  • add: Fügt Dateien und Verzeichnisse zur Versionskontrolle hinzu. Beim nächsten commit werden diese Dateien und Verzeichnisse in das repository hochgeladen und ab dann versioniert.
  • delete: Sieht eine Datei oder ein Verzeichnis zum Löschen beim nächsten commit vor.
  • lock: Sperrt eine Datei oder ein Verzeichnis. Möchte man nicht, dass eine andere Person im selben Zeitraum an der selben Datei oder am selben Verzeichnis Änderungen vornimmt, bietet sich dieses Kommando an. Es gibt aber nur seltene Fälle, in denen eine Sperre wirklich nötig ist. Nach der Bearbeitung muss unbedingt die Sperre mit “unlock” wieder aufgelöst werden!
  • unlock: Löst eine Sperre von einer Datei oder einem Verzeichnis.
  • cleanup: Bei der Arbeit mit Sperren (oder durch Bugs) kann es passieren, dass die Arbeitskopie in einem fehlerhaften Zustand vorliegt. Hier lohnt es sich, “cleanup” aufzurufen.

Die wichtigsten dieser Befehle sind auf jeden Fall “checkout”, “update”, “commit” und “resolve”. Diese Kommandos werden am häufigsten benutzt.

Die alltägliche Arbeit an Projekten mit Subversion gestaltet sich dann zeitlich ungefähr so:

  • checkout (einmalig)
  • update (um auf den aktuellen Stand zu kommen)
  • Arbeit am Projekt
  • update (um die Arbeit der anderen einfließen zu lassen [eventuell neuer Testlauf] und Konflikte zu bearbeiten)
  • möglicherweise Konfliktlösung
  • commit

Subversion bei MI

Während des Studiums wird Subversion in verschiedenen Projekten und Praktika genutzt. Passende Subversion-Repositorys werden von unseren Assistenten zur Verfügung gestellt. Die Adressen dieser repositorys sind neben den Adressen weiterer Dienste in diesem pdf einsehbar.

Prinzipiell halten wir uns an die übliche Struktur für repositorys: “trunk” für den Hauptentwicklungszweig, “branch” für Nebenzweige (weil man z.B. eine Alternative ausprobieren und damit parallel zum trunk arbeiten möchte), “tags” für wichtige, unveränderliche Versionen wie z.B. die Release-Version des Projektes. Andere Organisationsstruktur sind aber natürlich auch möglich und sollten dann im Team besprochen werden.

Tools für Subversion

Diese erweitern die durch das Betriebssystem oder die Entwicklungsumgebung zur Verfügung gestellten graphischen Oberfläche derart, dass der Versionierungs-Status einer jeden Datei direkt einzusehen und die Subversion-Befehle in passenden Kontextmenüs ausführbar sind. Dazu werden die Datei- und Verzeichnis-Symbole mit kleinen Zusatz-Icons “verschönert”.

Subversive

Subversive ist ein PlugIn für die Entwicklungsumgebung Eclipse. Es integriert Subversion und erlaubt so die Versionskontrolle direkt aus Eclipse heraus. Die Datei- und Ordnersymbole werden durch zusätzliche Icons erweitert und erhalten auch eine Anzeige über die jeweils vorliegende Revisionsnummer. Das Kontextmenü (also das “Rechtsklickmenü”) wird mit Subversion-Befehlen erweitert, neue, zusätzliche Perspektiven und Views werden zur Verfügung gestellt. So lassen sich einfach Projekte “aus-checken”, aktualisieren, Änderungen verfolgen und Konflikte (durch farbige Gegenüberstellung) lösen.

Neben dem Subversive SVN Team Provider wird auch ein Teil der Subversive SVN Connectoren – vorzugsweise SVNKit – benötigt. Die SVN Team Provider sind in den Standard-Eclipse-Distributionen in der Update-Seite enthalten; unter “Collaboration” ist der “Subversive SVN Team Provider (Incubation)” zu wählen. Für die SVN Connectoren sollte man Seite “http://community.polarion.com/projects/subversive/download/eclipse/2.0/update-site/” zu den Update-Seiten hinzufügen und aus dem Angebot zum Einen die “Subversive SVN Connectors” und zum Anderen die “SVNKit Implementation (Optional)”, derzeit in der Version 1.3.0, installieren.

Die Projektseite befindet sich hier.

TortoiseSVN

TortoiseSVN ist eine Erweiterung für den Explorer für Windows-Rechner. Einmal installiert, befinden sich alle Subversion-Befehle, die man benötigt, direkt im Kontextmenü und können so zu jeder Zeit auf beliebige Dateien und Ordner angewandt werden. Die Icons von versionierten Dateien und Verzeichnisse werden unten rechts durch aussagekräftige Symbole erweitert.

Näheres zu dem Explorer-PlugIn findet man zum Beispiel auf der Wikipedia-Seite oder der offiziellen Seite des Projektes.

SCPlugin

Dieses PlugIn setzt die Idee hinter TortoiseSVN für Mac OS X-Systeme um und erweitert deshalb das Kontextmenü des Finders. Den Download, genauere Beschreibungen und weiteres gibt es auf der Projektseite.

Weiterführende Links

Dieses HowTo erhebt keinen Anspruch auf Vollständigkeit. Subversion ist um einiges mächtiger, als hier beschrieben wurde. Nicht umsonst existieren sogar Bücher über Subversion. Deswegen gibt es hier zur Vertiefung, Recherche und als Referenz einige Links:

  • Wikipedia hilft generell beim Thema Versionsverwaltung und auch speziell bei Subversion weiter.
  • Die offizielle Projektseite liefert Downloads, Dokumentationen und vieles andere.
  • Zum Ausprobieren von Subversion lohnt sich eine kostenlose Registrierung bei https://opensvn.csie.org/, der Dienst ist zwar langsam, dafür aber gratis.
  • Der Chaos Computer Club e.V. hat sich in einer Ausgabe des Chaosradio Express des Themas “Verteilte Versionskontrollsysteme” angenommen. Es lohnt sich, reinzuhören!

Danke an Benjamin Trinczek für das Erstellen dieses HowTos.