Hilfe für Entwickler unter Linux


* Einführung * Installation * Paketmanager * Grundlagen * Shells * Entwicklung * KDE * Skriptsprachen * AWK * PHP * Perl * Apache * Veranstaltungen * Schulungen * Bücher * Netzwerk * OpenOffice * OpenSource * Samba

Entwicklung


© <a href="http://www.fotolia.de/p/29003">Ljupco Smokovski</a> - FOTOLIA
Home
Entwicklung von Programmen unter C
Versionsverwaltung mit RCS und CVS
Mit freundlicher Unterstützung von:

Linux-Kurse und Seminare Linux Kurse
Veranstalter des
Linux-Tag
am Bodensee
2007 und 2008

Kontakt
Haftung
Impressum
Problem Hilfe Startseite


© <a href="http://www.fotolia.de/p/30251">Franz Pfluegl</a> - FOTOLIAVersionsverwaltung 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:
 mkdir RCS

Ein bestehendes File, beispielsweise prog.c wird mit dem Befehl
 ci prog.c

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.
co -l prog.c

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
ci -u filename
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:

rcsdiff prog.c

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:

co -l r1.4 prog.c

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

rcsdiff -r1.4 prog.c

Will man eine Übersicht über die bisherigen eingecheckten Versionen plus der Kommentare, so kann man dazu den Befehl rlog benutzen:

rlog prog.c

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:
cvs checkout Beispiel

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:
cd Beispiel

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:

cvs update Beispiel

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:

  1. rm beispiel2.txt
  2. cvs remove -m "Datei wird nicht mehr benötigt" beispiel2.txt
  3. 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:

cvs diff beispiel2.txt

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:

cvs release -d Beispiel





Foto: © Franz Pfluegl - FOTOLIA

© Copyright 2007 - 2010, Bernd Klein mit freundlicher Unterstützung von Bodenseo, Linux-Kurse und Schulungen,
Foto linke Seite (Mann mit Strick und Colt): Foto: © Ljupco Smokovski, fotolia 984022