Subversion

Aus Das Sopra Wiki
Zur Navigation springen Zur Suche springen
Die druckbare Version wird nicht mehr unterstützt und kann Darstellungsfehler aufweisen. Bitte aktualisiere deine Browser-Lesezeichen und verwende stattdessen die Standard-Druckfunktion des Browsers.


Subversion (kurz: SVN) ist ein Versionsverwaltungssystem. Es wird verwendet um

  • Änderungen am Projekt zu protokollieren,
  • ältere Versionen wiederherzustellen,
  • das Projekt zu archivieren,
  • gemeinsames Arbeiten auf der selben Datenbasis zu ermöglichen,
  • kurz: es ermöglicht mehreren Entwicklern komfortabler an einem Projekt gemeinsam und gleichzeitig zu arbeiten.

Wir verwenden Subversion im Sopra um genau diese Punkte zu ermöglichen. Jede Gruppe erhält ihr eigenes Repository und auch ein Trac, um ihr Projekt zu verwalten.

Subversion besitzt eine Client-Server-Architektur, sodass man neben dem Original-Subversion-Client[1] auch einen beliebigen Subversion-Client verwenden kann. Grundsätzlich besteht eine Versionsverwaltung mit Subversion aus

zentrale Begriffe

Revision

Der Repository-Browser von TortoiseSVN mit markierter Revisionsspalte

Eine Revision ist ein atomarer Zustand des Repositorys, der für jede Datei und jedes Verzeichnis einzeln gespeichert und durch eine fortlaufende Nummer ausgedrückt wird. Die aktuelle Revision (auch: Die Head-Revision) eines Repositorys ist dabei die durch die letzte Änderung des Repositorys vergebene Zahl.

Jeder Commit eines Benutzers führt zu so einer Änderung am Repository und erhöht die Revision um 1.

Repository

Das Repository ist der zentrale Verzeichnisbaum, in dem sich alle unter Versionsverwaltung stehenden Dateien befinden. Das Repository kann alle Änderungen, die jemals an diesen Dateien oder Verzeichnissen vorgenommen wurden

  • nachvollziehen (d.h. angeben, welcher Autor welche Änderung durchgeführt hat),
  • rückgängig machen.

Working Copy

Die Working Copy (Arbeitskopie) ist ein Verzeichnis, das auf dem Rechner des Benutzers liegt und durch einen Checkout des Repositorys angelegt wurde. Es enthält eine Revision des Repositorys zusammen mit den lokalen Änderungen, die der Benutzer daran vorgenommen hat. Diese Änderungen können durch einen Commit mit dem zentralen Repository synchronisiert werden.

Die Working Copy kann durch ein Update auf den neuesten Stand (d.h. die neueste Revision) gebracht werden. Dabei können Konflikte entstehen.

Die Working Copy kann auch lokale Änderungen seit der letzen Synchronisation mit Revert rückgängig machen. Das funktioniert nicht nur für die gesamte Working Copy, sondern auch für jede einzelne Datei in ihr.

Mit Checkout und Update kann die Working Copy auch gezielt auf den Stand einer speziellen Revision gebracht werden.

Arbeiten mit Subversion

Wir beschreiben hier kurz und sehr abstrakt die einzelnen Funktionen, die ein Subversion-Client generell zur Verfügung stellt. Die genaue Funktionsweise kann von Client zu Client abweichen.

Projekt importieren

Mit Projekt importieren fügt man ein schon existierendes, nicht unter Versionsverwaltung stehendes, meist lokales, Verzeichnis zum Repository hinzu.

Achtung: Das lokale, hinzugefügte Verzeichnis wird dadurch NICHT zur Working Copy. Will man mit diesem Verzeichnis weiter arbeiten, muss man das Repository auschecken.

Projekt auschecken

Mit Projekt auschecken (SVN Checkout...) erzeugt man eine Working Copy in einem lokalen, leeren Verzeichnis. Diese Funktion wird nur einmal im Leben einer Working Copy verwendet.

Achtung: Auf keinen Fall einen Checkout in ein Verzeichnis machen, das bereits unter Versionsverwaltung steht.

Working Copy bearbeiten

Alle Dateien und Ordner in der Working Copy können nahezu genauso bearbeitet werden, als wäre die Working Copy ein normales Verzeichnis. Man kann Dateien und Verzeichnisse

  • neu anlegen
  • löschen
  • ändern
  • verschieben
  • umbenennen

Manche Veränderungen der Working Copy erfordern jedoch vor dem Commit eine explizite Mitteilung an die Versionsverwaltung. Wenn Dateien oder Verzeichnisse neu angelegt (Add...) oder gelöscht (Delete...) werden, kann das Repository nicht entscheiden, wie es darauf reagieren soll. Neue Dateien müssen nicht zwangsweise unter Versionsverwaltung gestellt werden, auch wenn sie in einer Working Copy liegen. Man könnte sie auch ignorieren. Gelöschte Dateien sollen nicht zwangsweise auch im Repository gelöscht werden, sie könnten auch von dort wiederhergestellt (z.B. mit Update) werden.

Noch größeren Aufwand benötigt das Umbenennen (Rename...) und das Verschieben von Dateien oder Verzeichnissen. Da zusätzliche Informationen mit einzelnen Dateien verknüpft sind, müssen diese Operationen vollständig durch den Client getätigt werden.

AnkhSVN übernimmt diese Arbeiten (zu einem Großteil) für den Benutzer, während man in TortoiseSVN diese Mitteilungen manuell vor einem Commit machen muss. Das Verschieben mit TortoiseSVN ist etwas versteckt, da dieser Befehl nur im Rechtsklick-Drag-and-Drop-Kontextmenü sichtbar ist.

Working Copy updaten

Ein Update-Log mit typischen Status-Meldungen (TortoiseSVN).

Mit dem Update der Working Copy (SVN Update) holt man sich die Änderungen der anderen Benutzer auf seinen Rechner. Dabei werden dem Benutzer die einzelnen Änderungen, die durch das Update an seiner Working Copy vorgenommen wurden, in einem Update-Log angezeigt. Je nach Client sieht das natürlich verschieden aus, aber die folgenden Aktionen wird man oft zu sehen bekommen[2]:

DeletedDie Datei wurde von einem anderen Benutzer in der Zwischenzeit gelöscht.
ConflictedDie Datei ist in einem Conflict-Zustand, d.h. seit dem letzen Checkout hat ein anderer Benutzer diese Datei geändert und sie wurde außerdem lokal geändert. Subversion kann diese Änderung nicht automatisch zusammenführen (da z.B. die selbe Zeile geändert wurde). Ein Conflict benötigt IMMER Benutzer-Interaktion um aufgelöst zu werden.
UpdatedDie Datei wurde seit dem letzten Checkout nicht lokal verändert, aber ein anderer Benutzer hat Veränderungen daran vorgenommen.
AddedEin anderer Benutzer hat diese Datei neu hinzugefügt.
MergedSeit dem letzen Checkout hat ein anderer Benutzer diese Datei geändert und sie wurde außerdem lokal geändert. In diesem Fall konnte Subversion die Änderungen automatisch zusammenführen (da z.B. der eine Benutzer nur den Anfang der Datei geändert hat, lokal aber nur das Ende geändert wurde)


Working Copy commiten

Wenn die lokalen Änderungen (für den Moment) abgeschlossen sind, können sie commited werden. Dadurch werden sie in das Repository eingefügt und den anderen Benutzern zur Verfügung gestellt.

Bei einem Commit sollte man auch immer eine Log-Message schreiben, sodass der Rest des Teams nachvollziehen kann, was (oder warum) man geändert hat. Sie sollten sich auf ein einheitliches Format (oder wenigstens eine Sprache) für diese Nachrichten einigen.

Sollte man beim Commit einen Fehler erhalten, kann dies mehrere Ursachen haben:

Sollte der Commit durch ein unerwartetes Ereignis unterbrochen werden, z.B. durch einen Stromausfall oder den Verlust der Verbindung zum Repository, sperrt Subversion die Working Copy und ignoriert diesen Commit im Repository, um inkonsistente Zustände zu vermeiden. In diesem Fall sollte vor einem erneuten Commit ein Cleanup der Working Copy durchgeführt werden.

Achtung: NIEMALS Änderungen einchecken, die das Repository breaken! Das sind Änderungen, die dazu führen, das das Projekt nicht mehr kompiliert. Die anderen Team-Mitglieder können dann ohne ihre Hilfe nicht mehr weiterarbeiten (und werden entsprechend dankbar sein)!

Revert

Mit svn revert macht man alle lokalen Änderungen rückgängig. Dabei werden sowohl die Änderungen des Inhaltes wie auch an den Metadaten (Zeit, Rechte etc.) rückgängig gemacht. Mit svn revert kann auch die Markierung um neue Dateien oder Verzeichnisse Hinzufügen/Löschen wieder entfernt werden. Die Auswirkungen von svn revert sind dabei auf die Arbeitskopie beschränkt (Das Projekt-Archiv bleibt unberührt).

Ignore

Man kann die meisten Subversion-Clients anweisen, bestimmte Dateien in allen folgenden Operationen zu ignorieren, d.h. sie explizit nicht unter Versionskontrolle stellen. Das ist insbesondere für temporäre Dateien (die z.B. bei jedem Build neu erzeugt werden) oder Benutzer-spezifische Einstellungen sinnvoll und muss von jedem verwendet werden. Die folgenden Dateien und Verzeichnisse müssen auf jedenfall auf die Ignore-Liste und dürfen nicht mit eingecheckt werden:

Warum?
binDie Dateien in diesem Ordner werden automatisch beim Kompillieren erstellt, sie hochzuladen ist also unnötig. Zudem sind auch binäre Dateien dabei die sich beim kompilieren häufig ändern. Da binäre Dateien nicht gemerged werden können wird das zu häufigen Konflikten mit den Commits anderer Teammitglieder führen.
objSiehe bin.
_ReSharper.#PROJEKTNAME#Dieses Verzeichnis wird vom Resharper automatisch generiert. Automatisch generierte Ordner sollen nicht ins SVN, siehe bin.
*.suoDie Dateien mit der Endung .suo (Solution User Options[3]) beinhalten eine Reihe von Benutzer-spezifischen Einstellungen für Visual Studio, die niemanden außer den Benutzer selber interessieren. Sie enthalten außerdem eine Reihe von absoluten Pfadangaben, die bei anderen Benutzern massive Probleme auslösen können. Sie sollen auf keinen Fall zum Repository hinzugefügt werden.
*.cachefileSiehe bin. Auch merkt sich MonoGame hier, welche Dateien es schon in ein ihm genehmes Format konvertiert hat. Wenn ein anderes Teammitglied eine neue Datei hinzufügt und diese Datei im .cachefile als bereits konvertiert markiert ist, kann es passieren daß sich XNA denkt "Hey die Datei hab ich doch schon" und sie nicht neu konvertiert.
*.DotSettings.userDiese Datei enthält Benutzerspezifische Resharper Einstellungen und soll entsprechend auch nicht eingecheckt werden.
*.thumbVon Windows generierte Datei, die Vorschaubilder für die Miniaturansicht im Explorer enthält.
thumbs.dbSiehe .thumb
.vsVon Visual Studio generiertes Verzeichnis für interne Einstellungen.

Hinweis: Bei Nutzung von TortoiseSVN als SVN Client müssen zuerst die Umgebenden Ordner eingecheckt werden damit die Ignore-Regeln gesetzt werden können! Also als erstes einfach das gesamte Projekt mit Ausnahme der zu ignorierenden Ordner und Dateien committen. Dann zu den zu ignorierenden Daten gehen und per Rechtsklick und Tortoise Menü auf die Ignore-Liste setzen (Das geht alternativ auch im Commit-Fenster). Sobald alle Ignore-Regeln gesetzt sind nocheinmal Committen damit die Ignore Regeln im SVN gespeichert sind.

Über die Kommandozeile fügt man Ordner/Dateien mittels svn propset svn:ignore <Datei/Ordnername> . hinzu. Oder man editiert die ignore Datei direkt mittels svn propedit svn:ignore . hier kann man durch newlines getrennt pattern für auszuschließende Objekte angeben

Diff

Mit Diff (in TortoiseSVN Show Modifications) kann man sich die Änderungen, die man seit dem letzten Checkout gemacht hat, anzeigen lassen. Das ist insbesondere für das Erstellen der Commit-Log-Message nützlich (man weiss wieder, was man eigentlich gemacht hat).

Conflicts

TortoiseSVN Dialog: Commit schlägt fehl, da foo.cpp in neuerer Revision vorliegt

Konflikte treten auf, wenn eine geänderte Datei committed wird, die in der Zwischenzeit in einer neueren Revision im Projekt-Archiv vorliegt. Konflikte bemerkt man entweder beim Committen svn: Out of date oder nach einem Update an der Markierung der Datei mit einem C.

Öffnet man die Datei sieht man die Konflikt behafteten Stellen:

<<<<<<< .mine
Das habe ich geschrieben
=======
Das steht in der letzten Revision im Projekt-Archiv (Hier Revision 42)
>>>>>>> .r42

Nach dem svn update sieht man jetzt 4 Versionen der betroffenen Datei foo.cpp

foo.cpp      -> Die Datei mit den Markierungen wie oben.
foo.cpp.mine -> Die Datei mit nur meinen Änderungen.
foo.cpp.r41  -> Die Datei vor meinen Änderungen. (Also Revision 41 der Datei).
foo.cpp.r42  -> Die Datei mit nur den Änderungen aus dem Projekt-archiv. (Also Revision 42 der Datei).

Jetzt kann mann sich entscheiden

Letzte Revision im Projektarchiv verwenden

Hier werden meine Änderungen verworfen (das bedeutet alles was ich an der conflicted Datei geändert habe ist verloren und wird auch in keiner History gespeichert) und es wird die Letzte Revision aus dem Projekt-Archiv verwendet.

svn resolve --accept theirs-full foo.cpp.

Meine Änderungen verwenden und die Änderungen an der Letzten Revision(en) wegschmeißen

Eine Möglichkeit wäre: Man löscht die Datei foo.cpp nennt foo.cpp.mine in foo.cpp um. Jetzt muss man SVN mitteilen, dass der Konflikt behoben ist indem man svn resolve foo.cpp ausführt. SVN kümmert sich um die foo.cpp.r<id> dateien. Das ganze geht auch mit einem Befehl: svn resolve --accept mine-full foo.cpp.

Jetzt sind in der aktuellen Revision nur meine Änderungen an der Datei. Alle Änderungen die in der Zwischenzeit vorgenommen wurden sind entfernt (allerdings noch in der History einsehbar).

Das beste aus Beiden Versionen behalten

TortoiseSVN Merge tool

Hier muss man die datei foo.cpp öffnen und alle Markierten Stellen von Hand bearbeiten, so dass am Ende das gewünschte übrig bleibt. Nach dem Speichern teilt man SVN mittels svn resolve foo.cpp mit das nun alles in Ordnung ist. SVN kümmert sich (löscht) die verbleibenden Dateien und man kann jetzt committen. Um sich den Prozess der Bearbeitung zu erleichtern gibt es auch eine ganze reihe Tools und Plugins für fast alle gängigen Editoren.

TortoiseSVN bietet einen Merge-Editor an. Diesen startet man für eine conflicted Datei mittels Rechtsklick auf diese wählt dann "Edit conflicts" dies öffnet den Editor (siehe rechts). Hier ist die obere linke Hälfte die aktuelle Revision im Projekt-Archiv (Mit "Theirs" betitelt). Die rechte Hälfte (mit "Mine" betitelt) öffnet die foo.cpp.mine datei. In Orange ist jeweils die Differenz markiert (die Zeile dient zur Orientierung wie sie vor dem Konflikt war). Im unteren Editor kann man nun unter jeder orangen Zeile entscheiden, welchen Teil man übernehmen möchte. Mit Rechtsklick auf die Zeile wählt man für jede Differenz Use text block from "theirs" für den Code aus der aktuellen Revision im Projekt-Archiv oder Use text block from "mine" um den Code aus meinen Änderungen zu benutzen. Man kann auch etwas komplett anderes direkt in die Zeilen Schreiben.

Ist man mit der Bearbeitung fertig, klickt man oben links aus "Save". Jetzt sollte man schauen, ob die Datei auch wirklich so ist wie man sie möchte und ob das Projekt noch kompiliert etc. Dann kann man die Datei mit Rechtsklick -> TurtoiseSVN -> Resolve (Dies ist auch in der Taskleiste im MergeEditor möglich) als "resolved" markieren und committen.

History

Die Show Log Ansicht von TortoiseSVN

Unter dieser Funktion versteht man die Überprüfung der Revisionsgeschichte (daher History) des Repository. Dazu stehen verschiedene Werkzeuge zur Verfügung:

  • List liefert eine Liste von Dateien/Verzeichnissen einer spezifischen Revision des Repositorys (in TortoiseSVN der Repo-Browser, der über das Kontextmenü erreicht wird.)
  • Log liefert alle Log-Messages einer Datei oder eines Verzeichnisses (Show Log in TortoiseSVN (ebenfalls über das Kontextmenü) liefert alle Log-Messages von allen Revisionen)
  • Cat gibt eine bestimmte Revision einer Datei auf den Bildschirm aus (in TortoiseSVN im Repo-Browser integriert)
  • Blame zeigt eine Datei an und ordnet jede Zeile einem Benutzer zu, sodass man sehen kann, wer wann welche Änderungen vorgenommen hat.


Cleanup

Das Cleanup-Kommando säubert rekursiv die Working Copy indem es Locks[4] entfernt und unterbrochene Operationen weiterführt (genauer: den Zustand so ändert, das er wieder konsistent ist).

Clients

Für die Entwicklung unter Windows haben wir gute Erfahrungen mit den zwei nachfolgenden Clients[5] gemacht. Wir empfehlen den Einsatz von beiden Clients gleichzeitg, da sie beide je nach aktueller Aufgabe gewisse, substantielle Vor- bzw. Nachteile aufweisen.

TortoiseSVN

TortoiseSVN ist ein Open-Source Subversion-Client für Windows, der sich in den Explorer integriert. Dieser Client besitzt im Gegensatz zu AnkhSVN eine sehr gute Unterstützung für die Auflösung von Konflikten in Form des (mitinstallierten) Programms TortoiseMerge.

Da TortoiseSVN eine exzellente Dokumentation besitzt, werden wir hier nicht auf die Bedinung und Installation eingehen. Bei Bedarf empfehlen wir die folgenden Links (die Handbücher sind sehr umfangreich, daher geben wir die Kapitel mit den für euch relevanten Informationen zusätzlich an):

AnkhSVN

AnkhSVN ist ein Open-Source Subversion-Client für Windows der sich direkt in Visual Studio integriert. Der große Vorteil dieses Clients besteht in eben dieser Integration, da man dadurch

  • neu angelegte Dateien automatisch zum Repository hinzufügt (und somit nicht mehr vergisst),
  • Dateien die gelöscht wurden nicht mehr zusätzlich im Repository löschen muss,
  • direkt weiß, welche Dateien sich geändert haben,
  • komfortabel Dateien verschieben kann (mittels Drag and Drop in der IDE,
  • die IDE nur noch in Ausnahmefällen verlassen muss.

Leider liefert AnkhSVN im Gegensatz zu TortoiseSVN kein "vernünftiges" Programm zum Editieren von Konflikten mit, sodaß wir lieber beide Programme gemeinsam benutzen. Auch für AnkhSVN gehen wir nicht weiter auf Bedienung und Installation ein, sondern verweisen auf die folgenden Seiten:

Web-Access

Unsere Repositorys können auch ohne Client über den Browser erreicht werden. Einfach den Pfad des Repositorys (siehe Gruppeneinteilung oder Abschnitt "Sopra Repository" für den eigenen Pfad) im Browser eingeben und mit den eigenen Zugangsdaten authentifizieren. Allerdings ist hierbei nur lesender Zugriff möglich.

Sopra Repository

Um auf das Gruppen-Repository zuzugreifen, braucht man:

  • einen IIF-Account (Poolaccount)

Der Pfad für das Repository ist https://sotec.informatik.uni-freiburg.de/svn/sopraXX wobei das XX für die Gruppennummer (01 bis 10) steht.

Trac und SVN

Das Projektmanagement-Werkzeug Trac ist im Softwarepraktikum auch mit dem Versionskontrollsystem Subversion verbunden. Dies erlaubt nicht nur, das Changelog über die Trac Weboberfläche einzusehen, sondern auch, Tickets über die Commit-Log-Messages zu referenzieren und zu schließen. Dabei wird die gesamte Log-Message eines Commits automatisch als Kommentar zu einem oder mehreren angegebenen Tickets hinzugefügt. Zusätzlich kann das entsprechende Ticket dabei auch geschlossen werden. Dies ermöglicht eine bessere Nachvollziehbarkeit (Traceability) der Projektentwicklung durch die Zuordnung von Änderungen des Projekts zu einzelnen Items im Product- bzw. Sprint Backlog.

Verwendung

Die Commit-Log-Messages werden nach Kommandos der Form [<Kommando> <Ticket> (<Konnektor> <Ticket>)*] durchsucht. Dabei stehen folgende Kommandos und Konnektoren zur Verfügung:

  • Ticket schließen (dabei wird immer die in Trac eingestellte Default-Resolution verwendet) und referenzieren: close, closed, closes, fix, fixed, fixes
  • Nur referenzieren: references, refs, addresses, re, see
  • Remaining Time ändern: remaining <ticketid>:<hours>
  • Konnektoren: , & and
  • Ticket-Schreibweise: ticket:<ticketid>, ticket<ticketid>, issue:<ticketid>, issue<ticketid>, bug:<ticketid>, bug<ticketid>, #<ticketid>,

Beispiele

Folgende Beispiele sind mögliche Commit-Log Messages:

Changed blah and foo to do this or that. [Fixes #10 and #12], and [refs #12].
This will [close #10 and #12].
Das betrifft [see #10, #12].
Ich habe an Ticket [see #13] weitergearbeitet. Die verbleibende Zeit ist nun [remaining #13:2h].

Die Kombination von Kommandos innerhalb einer Klammer ist allerdings nicht möglich. Folgendes Beispiel funktioniert nicht:

Ich muss sowieso mal das zumachen: [close #30, #51 and refs #50]

Im Moment funktioniert nicht, dass man die verbrauchte Zeit per Commit Message ändert. Bitte tragen Sie diese von Hand im Trac für Ihre Tasks nach, z.B. immer an einem festen Zeitpunkt in der Woche.

siehe auch

Referenzen

  1. offizielle Seite des Subversion-Projekts
  2. Für eine vollständige Liste siehe http://knaddison.com/technology/svn-status-code-cheat-sheet
  3. Solution User Options (.suo) in der MSDN
  4. Locks werden in diesem Artikel nicht behandelt, da wir glauben, das dieses Konzept überholt und - für uns - unnötig ist.
  5. für eine vollständigere Liste siehe Wikipedias Vergleich verschiedener SVN-Clients

Links