Versionsmanagementsysteme Motivation Mitglieder einer Software Entwicklungsgruppe müssen: gemeinsamen Zugriff auf die Projektressourcen haben (File Sharing) gleichzeitig identische Ressourcen bearbeiten können (Concurrent Editing) die Projekt-Historie der Ressourcen verfolgen können (File History) Ein Versionsmanagement-System liefert hier geeignete Software Mechanismen, um File Sharing, Concurrent Editing und File History zu ermöglichen. 1
Concurrent Editing Warum ist Concurrent Editing schwierig? Ein normaler File Server (z.b. NFS) kann File Sharing erleichtern, aber er kann immer nur die aktuelle Version der Datei speichern. diagram by Brian W. Fitzpatrick, C. Michael Pilato, Copyright 2000, 2001, 2002, 2003, 2004 CollabNet, Inc. Lock-Modify-Unlock Ein einfacher Mechanismus zur Concurrent Editing Unterstützung: Dieser Mechanismus kann benutzt werden, um einen multi-threaded Zugriff auf gemeinsame Ressourcen (Drucker) zu verwalten. diagram by Brian W. Fitzpatrick, C. Michael Pilato, Copyright 2000, 2001, 2002, 2003, 2004 CollabNet, Inc. 2
Lock-Modify-Unlock Nachteil dieses Ansatzes: Delays: Datei-Locking verhindert Concurrent Editing Administrative Overhead: Falls ein Entwickler vergisst, ein Datei-Locking freizugeben, dann muss dieser Lock explizit vom Administrator entfernt werden, bevor ein anderer Entwickler diese Datei neu editieren kann. False Sense of Security: Ein Datei-Lock einer einzelnen Datei A ist nicht ausreichend, wenn andere Dateien von Datei A implizit abhängig sind. Copy-Modify-Merge Ein besserer Mechanismus: diagram by Brian W. Fitzpatrick, C. Michael Pilato, Copyright 2000, 2001, 2002, 2003, 2004 CollabNet, Inc. 3
Copy-Modify-Merge Zwei Möglichkeiten können beim Zusammenfügen (merge) der Datei auftreten. Changes that do not overlap: trivial das Zusammenfügen kann automatisch passieren. changes that overlap: in diesem Fall tritt ein Konflikt auf und das Zusammenfügen wird schwieriger die Entwickler müssen gemeinsam entscheiden, welche Version übernommen wird soll (communication) Merging ist ein manueller Prozess der Entwickler. Kein Versionsmanagementsystem kann diesen Prozess abnehmen. Der Zeitbedarf, um diesen Konflikt zu lösen, ist wesentlich geringer als beim Lock-Modify-Unlock Ansatz. Versionsmanagement-Systeme 1985 RCS (Revision Control System): Lock-Modify-Unlock Strategie. Entwicklung von Prof. Tichy (Uni Purdue, Uni Karlsruhe) 1986 CVS (Concurrent Versions Systems): Copy-Modify-Merge Strategie. Erste Entwicklung von Dick Grune im Usenet verteilt, basierend auf Unix-Shell Skripten. 1989 CVS (Concurrent Versions Systems): Copy-Modify-Merge Strategie. Von Jeff Polk und Brian Berliner in C neu geschrieben. Open-Source, das dominante Versionsmanagement- System der letzten 15 Jahre, robust, konzeptionelle Schwachpunkte. www.cvshome.org 4
Versionsmanagement-Systeme 2004 Subversion Version 1.0 Copy-Modify-Merge Strategie Entwicklung von Karl Fogel (Author eines CVS Buches) Open-Source, Nachfolger von CVS subversion.tigris.org 2005 Subversion Release Version 1.1.3 Kommerzielle Versionsmanagement Systeme: 1998 BitKeeper Copy-Modify-Merge Strategie kommerzielles Produkt, kein Open-Source, benutzt in z.b. Linux Kernel Entwicklung! www.bitkeeper.com???? VSS (Visual Source Safe) Microsoft Client-Server Bestandteile Subversion Server: Repository: archiviert Projekt Ressourcen (Dateien, Quelltext, Makefiles, binäre Dateien) Subversion Server Subversion Clients (Entwickler): arbeiten lokal auf Arbeitskopien, holen Repository Updates, übermitteln Änderungen an den Server P1 W1 P2 W3 P3 P4 User 1 P1 checkout/update commit W1 W3 W4 User 2 5
Vorgehensweise Einrichten: Repository wird vom Administrator auf Server initialisiert (init). Entwickler importieren Projekt in das Repository (import). Benutzung: erstmals: Entwickler kopieren lokale Kopien (Arbeitskopie) des Projektes in lokales Verzeichnis (checkout) aktualisieren Arbeitskopie (update) übermitteln Änderungen (commit) Modell des kooperativen Entwickelns Einzelner Entwickler: Es kann durchaus sinnvoll ein Versionsmanagementsysteme als einzelner Entwickler einzusetzen (Tags, Entwicklungszweige, Historie, Backup, ). Mehrere Entwickler: Quelltext wird geteilt: Team ist für Quelltext verantwortlich. Entwickler arbeiten auf lokalen Kopien, niemals auf der Masterkopie. Kontrolle über den Quelltext hat das Versionsmanagementsystem, nicht der Entwickler (Backup, Versionsstände, ) Quelltext-Distribution übernimmt das Versionsmanagementsystem. 6
Entwicklungszyklen Start Arbeitskopie anfordern checkout commit Übernahme ins Repository Konflikte auflösen Entwicklung zur nächsten Teilversion Arbeitskopie abgleichen update Der Entwicklungszyklus Entwickler (Client) Server Repository Entwickler (Client) Server Repository leer Quelltext Lokale Arbeitskopie checkout Quelltext Entwickler (Client) Mischung aus lokalen und Repository Änderungen update Übertragung veränderter Dateien und Verzeichnisse gegebenenfalls Merging Server Repository Quelltext 7
Der Entwicklungszyklus Entwickler (Client) gegebenenfalls Konflikte beseitigt und neu getestet Keine Aktion Server Repository Quelltext Entwickler (Client) Dateien als svn resolved markieren Keine Aktion Server Repository Quelltext Der Entwicklungszyklus Entwickler (Client) Lokale Arbeitskopie wird geändert Keine Aktion Server Repository Quelltext Entwickler (Client) Entwicklungsteilschritt erreicht und gestestet commit update/commit Übertragung der veränderten Dateien und Verzeichnisse Server Repository Quelltext mit Änderungen des Entwicklers 8
Der Entwicklungszyklus Entwickler I Commit Server Repository Entwickler II Update Entwickeln Update Quelltext Commit Entwickeln Commit Update Entwickeln Entwickler III Einführung in CVS 9
CVS Client Installation CVS Server (z.b. enterprise.cs.unibas.ch) existiert schon. Passwort und Username ist vom Administrator eingerichtet. Linux Client: Download aktuelle Version (1.11.19) von http://www.cvshome.org # tar xzvf cvs-1.11.19.tar.gz # cd cvs-1.11.19 #./configure # make # su root # make install Windows GUI-Client: WinCVS: http://www.wincvs.org TortoiseCVS http://tortoisecvs.org CVS Umgebungsvariablen Man sollte mindestens die beiden folgenden Variablen setzen: Bevorzugter Editor z.b. % setenv CVSEDITOR emacs % setenv SVN_EDITOR emacs CVS Pfad auf lokalem Host z.b. /var/lib/cvsroot oder /cvs % setenv CVSROOT /cvs CVS Pfad auf Remote Host z.b. CVSROOT ext:username@enterprise.cs.unibas.ch:/cvs CVS_RSH ssh In allen SVN und CVS Beispielen wird abgenommen, dass diese Variablen gesetzt sind. 10
Beispiel einer Linux CVS Sitzung Kurze Beispielsitzung Programm TextPrinter.java zur Ausgabe eines Textes. Zwei Entwickler: Einlesen eines Textes aus einer Datei. Änderungen des Ausgabetextes. Hinzufügen einer weiteren Datei. Einbinden von I/O Java Paketen Beispiel einer Linux CVS Sitzung Anfangsprojekt: TextPrinter.java public class TextPrinter { public void printtext() { String text = readfile(); for (int i=0;i<text.length();i++) printchar(text.charat(i)); } private String readfile() { return "Beam me up"; } private void printchar (char ch){ System.out.print (ch); } public static void main(string[] args){ TextPrinter tp = new TextPrinter(); tp.printtext(); } } Projekt in CVS importieren: % ls demo TextPrint.java % cd demo import java.io.bufferedreader import java.io.filereader // It reads text.txt and // displays the string private String readfile() { String result = ""; try { BufferedReader br = new BufferedReader (new FileReader("text.txt")); String aline = br.readline(); while (aline!= null) { result += aline + "\n"; aline = br.readline(); } } catch { } return result; } % cat text.txt Beam me up, Scotty % cvs import demo -m "initial import" demo-project version-1-0 11
Entwicklung-Szenario Entwickler A checkout // It reads text.txt and // displays the string update commit % cat text.txt Beam me up, Scotty! update commit R e p o s i t o r y checkout import java.io.bufferedreader; import java.io.filereader; update commit Entwickler B private String readfile() { } update commit Konflikt auflösen Beispiel einer Linux CVS Sitzung Entwickler A Dateien aus Repository auschecken. Entwickler B % mkdir projecta % mkdir projectb % cd project % cd project % cvs checkout demo % cvs checkout demo cvs checkout: Updating demo cvs checkout: Updating demo U demo/textprinter.java U demo/textprinter.java % cd demo % cd demo % ls -F % ls -F % CVS/ TextPrinter.java % CVS/ TextPrinter.java CVS erzeugt Verzeichnis CVS/ mit Information über den Status der Arbeitskopie % ls CVS/ % ls CVS/ % Entries Repository Root % Entries Repository Root % cat Entries /TextPrinter.java/1.1.1.1/Tue Feb 22 14:24:19 2005// % cat Repository Demo % cat Root :ext:entwicklera@enterprise.cs.unibas.ch:/cvs 12
Beispiel einer Linux CVS Sitzung Entwickler A Entwickler B Beide Entwickler führen Änderungen auf der lokalen Arbeitskopie durch % emacs Textprinter.java % emacs Textprinter.java Line 1-2: // It reads text.txt and // displays the string % cvs diff cvs diff: Diffing. Index: TextPrinter.java RCS file: /cvs/demo/textprinter.java,v retrieving revision 1.1.1.1 diff -r1.1.1.1 TextPrinter.java 0a1,2 // It reads text.txt and // displays the string Line 1-2: import java.io.bufferedreader; import java.io.filereader; Entwickler A möchte die Änderungen in seiner lokalen Arbeitskopie überprüfen Entwickler A macht update der lokalen Arbeitskopie. % cvs update cvs update: Updating. M TextPrinter.java M bedeutet, dass sich Repository und lokale Arbeitskopie konfliktfrei zusammenführen lassen Beispiel einer Linux CVS Sitzung Entwickler A Entwickler A checkt ein (commit) % cvs commit -m "first comments" cvs commit: Examining. Checking in TextPrinter.java; /cvs/demo/textprinter.java,v <-- TextPrinter.java new revision: 1.2; previous revision: 1.1 done cvs diff zeigt die Änderungen zwischen der lokalen Arbeitskopie und der zuletzt ausgecheckten Repository Version an. cvs diff r HEAD zeigt die Änderungen zwischen der lokalen Arbeitskopie und der zuletzt ausgecheckten Version an. Entwickler B Entwickler B ist später soweit: % cvs diff cvs diff: Diffing. Index: TextPrinter.java RCS file: /cvs/demo/textprinter.java,v retrieving revision 1.1.1.1 diff -r1.1.1.1 TextPrinter.java 0a1,2 > import java.io.bufferedreader; > import java.io.filereader; % cvs diff r HEAD cvs diff: Diffing. Index: TextPrinter.java RCS file: /cvs/demo/textprinter.java,v retrieving revision 1.2 diff -r1.2 TextPrinter.java 1c1,2 < // It reads text.txt and < // displays the string --- > import java.io.bufferedreader; > import java.io.filereader; 13
Beispiel einer Linux CVS Sitzung Konflikt in Textprinter.java. Datei öffnen sie enthält an der Stelle des Konflikts beide Versionen: <<<<<<< TextPrinter.java import java.io.bufferedreader; import java.io.filereader; ======= // It reads text.txt and // displays the string >>>>>>> 1.2 public class TextPrinter { Originalversion liegt in.#textprinter.java.1.1.1.1 Konflikt beheben und commit durchführen Entwickler B Entwickler B macht Update. % cvs update cvs update: Updating. M TextPrinter.javaRCS file: /cvs/demo/textprinter.java,v retrieving revision 1.1.1.1 retrieving revision 1.2 Merging differences between 1.1.1.1 and 1.2 into TextPrinter.java rcsmerge: warning: conflicts during merge cvs update: conflicts found in TextPrinter.java C TextPrinter.java % ls AFl.#TextPrinter.java.1.1.1.1 CVS/ TextPrinter.java % cvs commit -m "with import" TextPrinter.java Checking in TextPrinter.java; /cvs/demo/textprinter.java,v <-- TextPrinter.java new revision: 1.3; previous revision: 1.2 done Entwicklung-Szenario Entwickler A % cat text.txt Beam me up, Scotty! update commit R e p o s i t o r y Entwickler B private String readfile() { } update commit 14
Beispiel einer Linux CVS Sitzung Entwickler A Hinzufügen einer Datei: text.txt % cat text.txt Beam me up, Scotty! % cvs update:? text.txt cvs update: Updating. P TextPrinter.java Datei text.txt im Repository anmelden % cvs add text.txt cvs add: scheduling file text.txt for addition cvs add: use cvs commit to add the file permanently % cvs commit -m "with Scotty cvs commit: Examining. RCS file: /cvs/demo/text.txt,v done Checking in text.txt; /cvs/demo/text.txt,v <-- text.txt initial revision: 1.1 done Entwickler B Editieren von TextPrinter.java private String readfile() { String result = ""; try { BufferedReader br = new BufferedReader (new FileReader("text.txt")); String aline = br.readline(); while (aline!= null) { result += aline + "\n"; aline = br.readline(); } } catch { } return result; } Beispiel einer Linux CVS Sitzung Entwickler A cvs update: M bedeutet, dass sich Repository und lokale Arbeitskopie konfliktfrei zusammenführen lassen C Konflikt U Datei erfolgreich aktualisiert. Entwickler A holt letzte Version % cvs update cvs update: Updating. P TextPrinter.java Entwickler B Entwickler B macht Update % cvs update cvs update: Updating. M TextPrinter.java U text.txt Entwickler B checkt ein (commit) % cvs commit -m "last version cvs commit: Examining. Checking in TextPrinter.java; /cvs/demo/textprinter.java,v <-- TextPrinter.java new revision: 1.4; previous revision: 1.3 done 15
Beispiel einer Linux CVS Sitzung % cvs log TextPrinter.java RCS file: /cvs/demo/textprinter.java,v Working file: TextPrinter.java total revisions: 5; selected revisions: 5 description: ---------------------------- revision 1.4 date: 2005/03/15 17:27:00; author: oschenk; state: Exp; lines: +19-1 last version ---------------------------- revision 1.3 date: 2005/03/15 17:15:41; author: oschenk; state: Exp; lines: +3-0 with import ---------------------------- revision 1.2 date: 2005/03/15 16:53:34; author: oschenk; state: Exp; lines: +2-0 first comments ---------------------------- revision 1.1 date: 2005/03/15 14:55:43; author: oschenk; state: Exp; branches: 1.1.1; Initial revision ---------------------------- revision 1.1.1.1 date: 2005/03/15 14:55:43; author: oschenk; state: Exp; lines: +0-0 initial import cvs log zeigt die gesamte Historie des Projektes an. Beispiel einer Linux CVS Sitzung % cvs log text.txt RCS file: /cvs/demo/text.txt,v Working file: text.txt head: 1.1 branch: locks: strict access list: symbolic names: keyword substitution: kv total revisions: 1; selected revisions: 1 description: ---------------------------- revision 1.1 date: 2005/03/15 17:18:43; author: oschenk; state: Exp; with Scotty ================================================================= 16
Administrative CVS Informationen Information ist im CVS/ Verzeichnis: Für jede Datei speichert CVS in CVS/: die aktuelle Revisionsnummer der Datei die Zeit des letzten Updates der Datei Basierend auf diesen Informationen entscheidet CVS, ob ein update oder commit die Daten im Repository ändert. Revisionsnummern TextPrinter.java text.text text2.text 1.1.1.1 1.2 1.1.1.1 1.2 1.1.1.1 Zusammengehörige Revision 1.3 1.4 1.5 Repository Dateien können in CVS unterschiedliche Revisionsnummer haben (auch wenn diese zum gleichen Projektstand gehören). Bestimmte Revisionsstände einer Datei können z.b. mit cvs update j 1.4 Textprinter.java wieder ausgecheckt werden. 17
Symbolische Tags TextPrinter.java 1.1.1.1 1.2 1.3 % cvs tag Release cvs tag: Tagging. T TextPrinter.java T text.txt T text2.txt text.text 1.1.1.1 % cvs log text2.txt RCS file: /cvs/demo/text2.txt,v Working file: text2.txt head: 1.1 symbolic names: Release: 1.1 text2.text 1.4 1.5 1.2 1.1.1.1 Markierte Dateirevision Release Tags werden häufig verwendet, um die Versionsnummer festzuhalten, die die Entwickler vergeben, anstatt der internen CVS Revisionsnummer. % cvs checkout r Release Verzweigungen (Branch) Was ist ein Branch? Verzweigung (eng. Branch): Ein Verzeigung ist eine neue unabhängige Entwicklungslinie des Projektes, welche die gleiche Historie mit anderen Linien besitzt. Einsatz von Verzweigungen? Release Versionen einer Software zur Fehlerbehebung. Fehlerbehebungsmanagement, experimentelle Versionen eines Projektes. In der Regel versucht man Verzweigung so schnell wie möglich wieder mit dem Hauptzweig zu vereinigen. 18
Die wichtigsten CVS Befehle checkout Vollständige Arbeitskopie aus dem Repository holen: cvs checkout demo add/delete Hinzufügen/Löschen von Datei/Verzeichnis im Repository. cvs add newfile.java cvs delete newfile.java commit Die lokalen Änderungen in das Repository übertragen. cvs commit -m "changes description" changed.java cvs commit kb m binäre Datei bild.png update Die Änderungen der anderen Entwickler übernehmen. cvs update outofdate.java help Hilfe zu dem einzelnen Befehlen: cvs help cvs add -help Einführung in Subversion 19
CVS Subversion Subversion und CVS sind sich grundsätzlich ähnlich. Ähnliche Syntax und Befehle z.b. für add, checkout, commit, import, update... Zugriffsverfahren über Client-Server-System: % cvs checkout d ext:username@enterprise.cs.unibas.ch:/cvs % svn checkout https://subversion.cs.unibas.ch/repos/ss05/cs104/g1 Es gibt unter Subversion keine Variable SVNROOT (import, checkout) Lokale Arbeitskopien und administrative Informationen:.svn anstatt CVS/ Caching bei Subversion: eine unveränderte Version jeder Datei liegt im.svn Verzeichnis. Damit müssen viele Befehle nicht über das Repository durchgeführt werden. Unterschiede CVS Subversion Atomaren Commits Was passiert wenn bei einem commit von mehreren Dateien festgestellt wird, dass für eine Datei im Repository Änderungen vorliegen, welche nicht in der Arbeitskopie vorliegen? CVS checkt die anderen Dateien ein. Subversion tritt bei einer Transaktion ein Fehler auf, so werden alle vorgenommen Änderungen rückgängig gemacht (Rollback) SVN Repository Revisionsnummern sind global Bei Subversion ändert sich die Revisionsnummer mit jedem einzelnen Commit % svn commit TextPrinter.java TextPrinter.java 11 text.text 11 SVN Repository Revisions- Nummer immer identisch 12 12 SVN Arbeitskopie Revisions- Nummer nicht identisch 20
Unterschiede CVS Subversion SVN Versionsverwaltung für Verzeichnisse Verzeichnisverwaltung unter CVS hat einige Schwachstellen. Konsistente Behandlung von Verzeichnissen unter SVN durch [mkdir, move, add, delete, copy]. Tags und Verzweigungen Subversion implementiert Tags und Verzweigungen durch Kopieren. Im Repository werden sie Projektverzeichnisse trunk, branches, tags angelegt. /repos/myproject/trunk /repos/myproject/branches /repos/myproject/tags [Hauptzweig] [Verzweigungen] [Versionen, Meilensteine] Behandlung binäre Dateien CVS kann binäre Dateien im Repository nicht effizient speichern. Subversion kann auch binäre Dateien gut verwalten. Unterschiede CVS Subversion Der SVN Befehl resolved Nach der Auflösung eines Konfliktes muss Subversion angezeigt werden, dass dieser beseitigt ist. Solange sich eine Datei im Konfliktzustand befindet, ist ein Einchecken in das Repository nicht möglich. Der Konfliktzustand muss explizit vom Entwickler zurückgesetzt werden. % svn resolved text.txt Resolved conflicted state of `text.txt % svn commit text.txt 21
Subversion Architektur Clients: svn (Linux) Tortoise (Windows) Repository Access URLs: file:/// http:// + https:// svn:// Programmieren II (CS104): https://subversion.cs.unibas.ch/repos/ss05/cs104/g1 https://subversion.cs.unibas.ch/websvn/wsvn/ss05/cs104 SVN Linux Befehle checkout Vollständige Arbeitskopie aus dem Repository holen: svn checkout https://subversion.cs.unibas.ch/repos/ss05/cs104/g1 add/delete Hinzufügen von Datei/Verzeichnis im Repository. cvs add newfile.java commit Die lokalen Änderungen in das Repository übertragen. svn commit -m "changes description" changed.java update Die Änderungen der anderen Entwickler übernehmen. svn update outofdate.java help Hilfe zu den einzelnen Befehlen: svn help svn help add 22
Windows Befehle TortoiseSVN Windows Befehle TortoiseSVN 23
Allgemeine Tipps Nur Quelltext einchecken, der getestet ist und funktioniert. Checken Sie nur Quellen ein, keine kompilierten Dateien (*.class, *.o) Möglichst kleine Änderungen, möglichst oft einchecken. Vor dem Commit immer ein Update durchführen und etwaige Konflikte auflösen. Wenn während des Updates Änderungen der anderen Entwickler vom Server geholt werden, den Code nochmals vor dem eigenen Commit testen. Hilfe Update, Commit usw. funktioniert nicht mehr neues checkout in ein anderes Verzeichnis machen, zuletzt geänderte Dateien hinüberkopieren. Wie sah der Code gestern aus, als alles noch funktionierte? Neuer checkout mit Revision {2005-05-19 15:30} % svn checkout - - revision " {2005-05-19 15:30} " Nach einem Konflikt lässt sich die Datei nicht mehr einchecken (remains in conflict) Konflikt beheben und % svn resolved Datei 24
Subversion Client Installation Aktuelle Linux Version unter http://subversion.tigris.org/project_packages.html # tar xzvf subversion-1.1.13.tar.gz # cd subversion-1.1.13 #./configure --without-apache --without-apxs -with-ssl --enable-shared --enable-static # make # su root # make install Windows: TortoiseSVN Download MSI Installer from http://tortoisesvn.tigris.org/download.html Dokumentation Allgemein: http://svnbook.red-bean.com Windows: http://tortoisesvn.tigris.org/docs.html Hilfe: svn help // List available commands svn help <command> // Help and argument list // for <command> 25