Entwicklung
Home
Entwicklung von Programmen unter C
Versionsverwaltung mit RCS und CVS
Mit freundlicher Unterstützung von:
Linux-Kurse und Seminare
Veranstalter des
Linux-Tag am Bodensee 2007 und 2008
Kontakt
Haftung
Impressum
Problem Hilfe Startseite
|
Versionsverwaltung
mit RCS und CVS
Eine Versionsverwaltung, auch Versionsmanagement-System genannt, ist
ein Programmpaket, welches meist in der Softwareentwicklung zur
Versionierung von Dateien, d.h. es hilft dem oder den Anwendern
seine Dateien, z.B. Quellen von C-Programmen, zu verwalten, zu
archivieren oder wenn nötig wieder herzustellen. Zu diesem Zweck
protokolliert die Versionsverwaltung alle Änderungen die an einer
unter seiner Verwaltung stehenden Dateien vorgenommen werden. Dadurch
wird es möglich Änderungen auf einfache Art und Weise wieder
rückgängig zu machen.
Die wichtigsten Aufgaben eines Versionsverwaltungssystems
- Protokollierungen aller
Änderungen
Dadurch wird eine hohe Transparenz erreicht, d.h. man kann jederzeit
nachvollziehen, welche Änderungen
zu welchem Zeitpunkt und von
welchem Nutzer
durchgeführt worden waren.
- Wiederherstellung von alten
Ständen einzelner Dateien
Die konsequente Protokollierung ermöglicht die systematische
Rückgägngimachung von Änderungen, d.h. man kann wieder
auf alte definierte und korrekte Zustände zurückgreifen.
- Archivierung
- Gemeinsamer Zugriff von mehreren Nutzern auf die Dateien
Dies wird nicht von jeder Versionsverwaltung ermöglichst. So
bietet CVS dieses Feature, während RCS dies nicht
unterstützt. Der gemeinsame Zugriff erfordert auch Stretegien, die
dadurch auftretenden Konflikte aufzulösen. Ein solcher Konflikt
entsteht z.B. wenn zwei Nutzer zur gleichen Zeit die gleiche Datei
bearbeiten und anschließend ihre geänderte Version wieder
abspeichern wollen.
- Gleichzeitige Verfolgung verschiedener Entwicklungszweige (engl.
Branches) eines Projektes
RCS
RCS ist eine Versionsverwaltung, die auf einem Verzeichnis arbeitet. Es
verwaltet Textdateien, wie Quelltexte von Programmen,
Konfigurationsdateien, LaTeX-Dateien, Dokumentationsdateien und so
weiter. Da RCS nur einzelne Dateien in einem Verzeichnis verwaltet,
eignet es sich nur sehr bedingt zur Verwaltung von Software-Projekten.
Im letzteren Fall empfiehlt es sich CVS zu benutzen.
Um mit RCS in einem Verzeichnis zu arbeiten, legt man in diesem
Verzeichnis ein Unterverzeichnis mit dem Namen RCS an:
Ein bestehendes File,
beispielsweise prog.c wird mit dem Befehl
der Versionsverwaltung RCS übergeben. Nach Eingabe von obigem
Kommando auf der Shell wartet das Programm mit der Meldung
enter description, terminated with single
'.' or end of file:
NOTE: This is NOT the log
message!
>>> |
Das heißt, dass ein Kommentar
zu dieser Version erwartet wird. Der Kommentar muss mit einem Punkt als
Ende abgeschlossen werden.
Anschließend befindet sich im Unterverzeichnis RCS eine Datei mit
dem Namen prog.c,v. In dieser Datei werden dann alle Änderungen,
die an prog.c zukünftig vorgenommen werden gespeichert. Im
Verzeichnis selbst ist die Datei verschwunden. Möchte man mit
diese Datei weiterverarbeiten, was normalerweise der Fall sein wird,
muss man sie wieder mit folgendem Kommando auschecken.
Damit wird wieder eine editierbare Kopie von prog.c im Verzeichnis zur
Verfügung gestellt.
Wenn man wieder mit dem Editieren fertig sind, kann man das File wieder
wie oben beschrieben einchecken, also "ci prog.c".
Will man immer eine editierbare Version haben, empfiehlt es sich, statt
der Befehlsfolge "ci filename" und "co filename" die Abkürzung
zu verwenden.
Damit hat man bereits die wichtigsten Befehle zusammen, um mit RCS zu
arbeiten. Allerdings wird man bald in die Sitation kommen, dass man
gerne wissen will, worin die Änderungen bestehen zwischen der
Datei, die man gerade editiert und der letzten Version unter
RCS-Verwaltung. Dazu gibt es den Befehl rcsdiff. In unserem Beispiel
sieht das so aus:
Wenn wir in unserem C-Programm als einzige Änderung die Zeile (den
Kommentar)
/* Ein Kommentar um die Arbeitsweise von rcsdiff zu veranschaulichen */"
aufgenommen haben, liefert rcsdiff
prog.c die folgende Ausgabe:
===================================================================
RCS file: RCS/prog.c,v
retrieving revision 1.1
diff -r1.1 prog.c
1a2
> /* Ein Kommentar um die
Arbeitsweise von rcsdiff zu veranschaulichen */
|
Ein interessantes Feature von RCS besteht in der
Schlüsselwort-Substitution. Fügt man beispielsweise in
unserer Beispieldatei die Zeile $Date$ ein, so wird nach einem
nochmaligen "ci -l progr.c" das Datum in der Form mit "$Date:
2006/11/20 16:11:19 $"eingefügt. Da es sich um ein C-Programm
handelt, sollte man solche Informationen natürlich in Kommentare
packen, also /* $Date$ */
Weitere Schlüsselwörter:
$Author$
|
Benutzername
|
$Date$
|
Datum und Uhrzeit des Eincheckens
|
$Header$
|
voller Pfadname des RCS-Files,
revision number, Datum, Autor, Zustand und falls die Datei gesperrt
(locked) ist, auch den Namen der Person, die das File gesperrt hat.
|
$Id$
|
wie $Header$, aber ohne vollen
Pfadnamen, d.h. nur der Dateiname
|
$Locker$
|
Name der Person, welche die
Datei gesperrt hat.
|
$Log$
|
Kommentar, der beim Checkin
eingegeben wurde
|
$RCSfile$
|
Name des RCS-Files ohne Pfadnamen
|
$Revision$
|
Die zugewiesen Versionsnummer
|
$Source$
|
Der RCS Dateiname ohne Pfadname
|
$State$
|
Der Zustand der durch die -s
Option von ci oder rcs zugewiesen wurde
|
Möchte man eine bestimmte Version auschecken, z.B. 1.4, so geht
dies mit der -r Option:
Eine mögliche weitere Situation, die sich während der Arbeit
einstellen könnte, besteht darin, dass man gerne die aktuelle
Version, d.h. diejenige, die man gerade bearbeitet mit einer alten
Version vergleichen will. Dies geschieht dann mit der
Will man eine Übersicht über die bisherigen eingecheckten
Versionen plus der Kommentare, so kann man dazu den Befehl rlog
benutzen:
CVS
CVS (Concurrent Version System) gehört zu denen am
häufigsten eingesetzten Versionsverwaltungssystemen. CVS eignet
sich auch für den Einsatz in großen Projekten, was im
allgemeinen vielen Dateien und und eine große Zahl von
Entwicklern auf verschiedenen Rechnern bedeutet.
In der Philosophie von CVS stellt ein Projekt ein UNIX-Dateibaum mit
den dazugehörigen Dateien dar. An einem Ort, dem sogenannten
repository (engl. Lagerstätte, Aufbewahrungsort) (cvsroot), werden
die verschiedenen Versionen der einzelnen Dateien mit ihren
Änderungsprotokollen aufbewahrt oder archiviert.
Normalerweise werden nur die Quellen eines Projektes unter die
Verwaltung von CVS gestellt. Daten. Es macht keinen Sinn, Daten, die
sich automatisch aus den Quellen erzeugen lassen unter die Verwaltung
von CVS zu stellen, wie z.B. die o-Files von C oder ide class-Files von
Java oder die von LaTeX erzeugten dvi-Dateien.
Gearbeit wir auf lokalen Kopien, die in verschiedenen Verzeichnissen
und bei verschiedenen Nutzern vorhanden sein können.
Es werden keine Locking-Mechanismen benutzt.
Anlegen eines Projektes unter CVS
Wir legen zunächst ein Arbeitsverzeichnis an, zum Beispiel mit dem
Namen cvstest. Dieses Verzeichnis kann sich an beliebiger Stelle
im Dateibaum befinden, also auch im Homeverzeichnis.
Bei den folgenden Kommandos wird nun angenommen, dass man sich im
Verzeichnis "cvstest" befindet.
Um mit CVS arbeiten zu können benötigt man ein
Projektverzeichnis, hier CVS_repository genannt, auf das alle Nutzer
des Projektes, z. B.
Entwickler, zugreifen können. Im folgenden Beispiel wird ein
solches Verzeichnis im Ordner /data angelegt:
cvs -d /data/CVS_repository init
|
Nach Ausführung dieses Kommandos befindet sich in /data ein
Unterverzeichnis mit dem Namen "CVS_repository", in dem ein wiederum
ein Unterverzeichnis CVSROOT angelegt wurde.
Die Angabe der -d Option mit dem Pfad kann man sich sparen, wenn man
die Umgebungsvariable CVSROOT entsprechend setzt. In der
Bash-Shell geht dies mit dem Kommando:
export CVSROOT=/data/CVS_repository/
|
In diesem Verzeichnis CVSROOT befinden sich nach der obigen
Ausführung des "cvs init" mehrere Dateien und ein Unterverzeichnis
"Emptydir", wie ein ls-Befehl zeigt:
saturn:/data > ls
/data/CVS_repository/CVSROOT/
checkoutlist
config,v loginfo
notify,v posttag
preproxy,v val-tags
checkoutlist,v
cvswrappers loginfo,v
postadmin posttag,v
rcsinfo verifymsg
commitinfo
cvswrappers,v modules postadmin,v
postwatch rcsinfo,v verifymsg,v
commitinfo,v
Emptydir modules,v
postproxy postwatch,v taginfo
config
history
notify postproxy,v
preproxy taginfo,v
|
Nun können wir ein Projekt in unser neu eingerichtetes Repository
importieren. Unser Beispielprojekt nennen wir "Beispiel". Das leere
Projekt "Beispiel" kann man jetzt wie folgt in CVS importieren:
cvs import -m "Ein einfaches Beispiel
unter CVS" Beispiel Firmenname Ausgabezusatz
|
Der String hinter der -m-Option "Ein einfaches Beispiel unter CVS" ist
die Änderungsmeldung. "Beispiel" gibt den Namen des Projektes an.
Die Attribute Firmenname und Ausgabezusatz müssen angegeben
werden, spielen aber in unserem einfachen Fall keine Rolle.
Folgende Ausgabe sollte nach der Eingabe des cvs-import-Befehls
erscheinen:
No conflicts created by this import
|
Im Verzeichnis /data/CVS_repository gibt es nun parallel zu CVSROOT ein
noch leeres Unterverzeichnis Beispiel.
Um nun mit dem neuen Projekt "Beispiel" arbeiten zu können,
müssen wir es wieder auschecken:
Nach dem Checkout befindet sich im Arbeitsverzeichnis, was in unserem
Fall cvstest heißt, ein Unterverzeichnis mit dem Namen
"Beispiel", also gleichnamig zu unserem Projekt. In dem Verzeichnis
Beispiel befindet sich ein Unterverzeichnis CVS mit für das
CVS-System wichtigen Informationen.
Nun wollen wir eine Datei "für unser Projekt" erzeugen. Dazu
müssen wir uns von cvstest in das Unterverzeichnis Beispiel
bewegen:
Mit einem Editor erzeugen wir nun eine Datei mit dem Namen beispiel.txt
und speichern sie im aktuellen Verzeichnis (Beispiel). Nun fügen
wir die Datei beispiel.txt CVS hinzu:
cvs add -m "Eine erste Beispieldatei"
beispiel.txt
|
Folgende Ausgabe erscheint:
cvs add: scheduling file `beispiel.txt'
for addition
cvs add: use `cvs commit' to
add this file permanently
|
Die Ausgabe bedeutet in etwa, dass unsere Datei zum Hinzufügen
vorgemerkt ist. Allerdings muss noch das Kommando "cvs commit"
ausgeführt werden, um dies dauerhaft zu machen, d.h. sie ins
Repository einzufügen und damit ihre Versionsnummer
hochzuzählen. Damit kann man warten bis man noch eine zweite
Datei, z.B. beispiel2.txt hinzugefügt hat:
cvs add -m "Noch eine Datei, weil's so
toll war" beispiel2.txt
cvs commit -m "Beide Dateien
zusammen ins Repository" beispiel.txt beispiel2.txt
|
Die Ausgabe des commit-Kommandos:
/data/CVS_repository/Beispiel/beispiel.txt,v
<-- beispiel.txt
initial revision: 1.1
/data/CVS_repository/Beispiel/beispiel2.txt,v <--
beispiel2.txt
initial revision: 1.1
|
Damit sind nun die Änderungen an beispiel.txt und beispiel2.txt im
Repository übernommen.
Arbeitet man mit mehreren Kollegen an einem Projekt empfiehlt es sich,
die Änderungen von Zeit zu Zeit in die Arbeitskopie zu
übernehmen:
Im Laufe der Arbeit stellt sich auch sicherlich das Problem, dass man
eine Datei wieder löschen will, in unserem Beispiel die Datei
beispiel2.txt. Da man nun unter CVS arbeitet kann man die Datei nicht
einfach nur mit rm aus der Arbeitskopie entfernen, sondern muss sie
auch aus dem Repository entfernen. Die Löschung erfolgt in drei
Schritten:
- rm beispiel2.txt
- cvs remove -m "Datei wird nicht
mehr benötigt" beispiel2.txt
- cvs commit -m "Datei
beispiel2.txt entfernt" beispiel2.txt
|
Im Folgenden wollen wir uns anschauen, wie man die lokale Arbeitskopie
mit der Version im Repository vergleicht:
Will man die Arbeitskopie mit einer bestimmten alten Version
vergleichen, geht das mit der -r Option:
cvs diff -r <Version> beispiel2.txt
|
Wenn man seine Änderungen im Repository eingetragen hat, kann man
seine Arbeitskopien wieder löschen. Dazu muss man über dem
Verzeichnis der Arbeitskopie stehen, d.h. wenn man in dem Verzeichnis
steht, muss man sich mit "cd .." höher bewegen. Mit Release wird
dann das Verzeichnis gelöscht:
Foto: © Franz Pfluegl -
FOTOLIA
|