Howto CVS
Von Claus Ebert
Version 0.12
Klar! Als Entwickler ist ein Versionsverwaltungssystems ein muß. Dazu bietet sich CVS, als Standard der Open Source Szene an. Es gibt aber einige Fallstricke beim Installieren und Konfigurieren,und an die Synatx muß man sich auch erst gewöhnen.
1.1 WinCVS
WinCVS ist ein Grafisches Frontend für CVS unter Windows.
Wenn die Entwicklungsungebung CVS nicht unterstützt, ist WinCVS ein sehr nützliches Tool. Die einzige Wichtige einstellung ist die des
CVSROOT. z.B:
CVSROOT=:pserver:user@cvs.example.org:/usr/local/cvsroot
Hinweis:
Leider kommt WinCVS mit der Port-Angabe im CVSROOT nicht zurecht.
WinCVS interpretiert die Portnummer (zumindest bei mir) als Teil des Pfades zum Repository, was immer
in einer Ablehnung der Verbindung beim
cvs logon
endet.
Das einzige was bei mir geholfen hat, ist, den Port im Einstellungsdialog einzugeben und NICHT
über die CVSROOT Variable zu setzen.
top
1.2 CVS unter AIX
Da der CVS Standard Port 2401 unter AIX (leider) schon vergeben ist, muß man einen anderen Port verwenden (in meinem Fall 2402).
Mein Kollege hat dazu CVS für diesen Port als Defaultport kompiliert (auch ne lösung ;-)).
Es sollte aber auch über die Environment-Variable
CVS_CLIENT_PORT
oder direkt mit der
CVSROOT
- variable gehen (
CVSROOT=:pserver:user@cvs.example.org:2402/usr/local/cvsroot
).
Hier ist wieder der Pfad hinter der Port Nummer zu beachten.
TIP:
ein
touch ~/.cvspass
hilft, wenn cvs das File nicht selbst anlegen kann.
top
2.1 CVS Server unter AIX einrichten
Leider ist der CVS Standard Port (2401) unter AIX schon vergeben, also nehmen wir den nächsten verfügbaren.
In meinem Fall war das Port 2402.
Also frisch ans Werk:
Zuerst muß in der Datei
/etc/services
die Zeile
cvspserver 2402/tcp
eingefügt werden.
Jetzt müssen wir nur noch dem
inetd
sagen was er tun soll.
Dazu fügen wir in die Datei
/etc/inetd.conf
folgende Zeile ein:
cvspserver stream tcp nowait root /usr/local/bin/cvs
cvs -f --allow-root=/usr/cvsroot pserver
Die beiden Zeilen oben müssen hintereinander in einer Zeile stehen
Unter --allow-root={pfad} sollte ein eingerichtetes Repository verfügbar sein (siehe
Einrichten eines Repositories
).
Das war es eigendlich schon. Nun muß nur noch dem Client beigebracht werden,
das er den Port 2402 verwenden soll.
top
2.2 CVS Server unter Linux/Debian einrichten
Unter Debian ist es eigendlich ganz einfach: mit
>apt-get install cvs
CVS installieren. Danach müssen die Fragen nur noch beantwortet werden und der
CVS-Server sollte betriebsbereit sein.
Falls die configuration wiederholt werden soll, dann hilft einem ein
>dpkg-reconfigure cvs
bestimmt weiter.
top
3.1 Einrichten eines Repositories
Das CVS-Repository ist das zentrale Verzeichnis, in dem alle Dateien und Unterverzeichnisse verwaltet werden.
Ich nehme hier als Beispiel ein CVS Repository in
/var/log/CVS
an. Deswegen sollte als Vorbereitung die Umgebungsvariable CVSROOT auf dieses Verzeichnis gesetzt werden, z.B. in der bash mit:
>export CVSROOT=/var/log/CVS
Ein Repository kann als root angelegt werden, mit:
mkdir -p /var/log/CVS/CVSROOT
mkdir -p /var/log/CVS/Module
In
/var/log/CVS/
speichert CVS seine Daten. CVS nennt dies ein Repository.
In
/var/log/CVS/Module
speichert CVS die Daten zum Projekt
Module
Doku. CVS nennt dies ein Modul.
Falls noch nicht geschehen sollte jetzt die CVS-Gruppe und der CVS-User angelegt werden:
>groupadd cvs
>useradd -g users -G cvs -m cvs_user
>cd /var/log/CVS
>chown -R cvs_user.cvs Module
groupadd und useradd brauche ich hier nicht zu beschreiben.
Wichtig ist nur daß das Repository dem CVS-User (cvs_user) zugewiesen werden muß
und er schreibrechte auf alle Modul-Unterverzeichnisse hat.
Wichtig!!!
Nie die Dateien im Repository direkt ändern !!!
Wichtig!!!
Verzeichnisse sind später nicht zu entfernen !!!
Zu guter letzt müssen wir cvs nur noch das Repository initialisieren lassen. Das tun wir mit:
>cvs -d /var/log/CVS init
cvs init ist "vorsichtig". D.h. es löscht nie Dateien im Repository, könnte also gefahrlos auch
später aufgerufen werden.
Wir haben nun ein leeres Repository angelegt.
Um es mit Leben zu füllen müssen wir zuerst ein Modul in das Repository
importieren
top
3.2 Importieren in das Repository
In das Repository kann von jedem Rechner in Netzwerk importiert werden. Vorausgesetzt wird lediglich, das CVS installiert und die Environment-Variable
CVSROOT
gesetzt ist.
Alle Dateien, die sich in dem Verzeichnis befinden, in dem wir momentan sind weden mit
>cvs import -m "initial Import" Module Original alpha
in das Repository aufgenommen.
Beim Import erwartet CVS diese Syntax:
>cvs import -m <Kommentar> <Modul-Name> <Vendorname> <Revision-tag>
Vendorname und Revision-Tag müssen angegeben werden, aber der Inhalt ist beliebig. CVS nimmt nun die Daten in seine Verwaltung auf.
Falls man den gerade importierten Versionsstand wieder (trotz einiger Änerungen) wieder restaurieren will, empfiehlt es sich, jetzt ein Tag zu setzen:
>cvs tag -F Original Module
Die Daten im jetztigen Zustand bekommen den Tag "Original".
Der Parameter
-F
bedeudet Force und überschreibt ein Tag falls es schon im Repository vorhanden sein sollte.... hmmm ...
OK. Wenn eine Datei im Repository bereits mit diesem Tag markiert ist, aber bereits eine (einige) neue Versionen dieser Datei committet wurden, dann wandert das Tag zu der neuesten Version der Datei.
Dieser Parameter eignet sich also auch um ein Tag zu einer neueren Version zu verschieben.
Dies ist aber mit Vorsicht zu geniesen, da so die konsistenz der 'alten' Version dann nicht mehr gewährleistet ist.
top
3.3 Auschecken (cvs checkout)
>cvs checkout -r Original Modul
CVS erzeugt im aktuellen Arbeitsverzeichnis das Unterverzeichnis
Modul
an und exportiert alle im Repository befindlichen Dateien und Unterverzeichnisse des Moduls
Modul.
Der Parameter
-r
bedeudet das alle Dateien die mit dem Tag
Orginal
markiert wurden exportiert werden.
Auschecken in ein anderes Verzeichnis, als durch den Modulnamen vorgegeben:
Mit dem Parameter
-d
kann man angeben, in welches Verzeichnis das Modul ausgecheckt werden soll.
z.B :
>cvs checkout -d neuModule Module
veranlasst cvs das Modul
Module
in das Verzeichnis
neuModule
auszuchecken.
top
3.4 Änderungen dem Repository hinzufügen (cvs commit)
>cvs commit Module
Durch diesen Befehl werden die geänderten Daten ins Repository übernommen, dazu wird der Editor aufgerufen und ein Kommentar kann zu den Änderungen eingegeben werden.
Welcher Editor verwendet wird, kann man über die Environment-Variable
EDITOR
festlegen.
z.B:
>cvs tag -F alpha1 Module
versieht die aktuelle Version mit einem neuen Versions-Tag.
top
3.5 Hinzufügen von Dateien
Hinzufügen einer Datei: (in diesem Fall der Datei
tuWas
)
>cd Module
>vi tuWas ... <esc> :wq!
(Windows: einfach Notepad benutzen)
>cvs add tuWas
Datei wird fürs Hinzufügen NUR vorgemerkt! Mit einem
>cvs commit
wird die neue Datei ins Repository aufgenommen.
Jetzt ist ein guter Zeitpunkt ein neues Versions-Tag zu setzen. Das beschieht folgendermaßen:
>cd ..
>cvs tag -F "tuWas_hinzugefuegt" Module
Der neue Versions-Tag ist gesetzt. Verzeichnisse werden analog hinzugefügt. Jedoch geschieht dies nicht rekursiv!
top
3.6 Entfernen von Dateien
Im CVS-Kontext bedeutet das Entfernen einer Datei, daß die alte Version im Repository erhalten bleibt, aber beim checkout nicht mehr ausgeliefert wird.
>cd Module
>rm tuWas
entfernt die Datei
tuWas
aus dem Arbeitsverzeichnis.
>cvs remove tuWas
markiert die Datei
tuWas
zum löschen. Aber erst mit
>cvs commit
wird das "löschen" ausgeführt.
Die Datei wird bein nächsten checkout oder update nicht mehr berücksichtigt.
>cd ..
>cvs tag -F "tuWas entfernt" Module
Tagt (Markiert) alle Dateien des Moduls.
top
3.7 Entfernte Datei zurückholen
Um die Datei
tuWas
wieder zurückzuholen müssen wir dem
checkout
Kommando sagen welche Version wir haben wollen.
>cvs checkout -r "tuWas_hinzugefuegt" Module
Dies hat aber einen "sticky" Tag zur Folge. "sticky" meint in diesem Fall, daß die durch
-r {Version}
mitgegebene Version bis auf weiteres diejenige bleibt, auf die sich die folgenden Updates beziehen.
>cvs update -A
holt die neueste Version und entfernt dabei "sticky" Tags
>cvs update -p -r "tuWas_hinzugefuegt" Module
holt die ältere Version, in der die Datei noch existiert, gibt diese aber einfach in die Konsole aus.
top
3.8 Datei umbenennen
Um eine Datei umzubenennen, genügen einige einfache Kommandos:
>mv foo bar
Die Datei foo in bar umbenennen.
>cvs remove foo
Die Datei foo im CVS-Repository als entfernt markieren.
>cvs add bar
Die neue Datei bar hinzufügen.
>cvs commit -m "Renamed foo to bar" foo bar
Die Änderungen ins repository übernehmen.
Dabei ändert sich die Versionsnummer. Wenn das nicht gewünscht wird, kann mit
>cvs commit -r 3.0
eine Versionsnummer vorgegeben werden.
Achtung: Die neue Versionsnummer muß höher sein als alle aktuell im Modul verwendeten.
top
3.9 alte Versionen benutzen
Um eine Datei in einer alter oder getaggten Version aus CVS herauszuholen
benutzen wir den
Update
-Befehl zusammen mit der
-r
option
>cvs up - r 1.12 Makefile
Hiermit wird die Date Makefile aud die im Reposotory vorhandene Version 1.12
up- oder downgegradet.
Das ganze funktioniert natuerlich auch für getaggte Versionen
>cvs up - r "TESTVERSION" Makefile
hiermit wird das Makefile mit dem Tag
TESTVERSION
aus dem Repository geholt
Das ganze kann natürlich auch mit
find
kombiniert werden:
>find . -name Makefile -exec cvs update -r TESTVERSION '{}' \;
hiermit wird das Makefile mit dem Tag
TESTVERSION
aus dem Repository für dieses und alle Subdirecturies geholt
top
3.10 Unterschiede zwischen Versionen
Der
-Befehl liefert die Unterschiede zwischen der Datei im lokalen Verzeichnis und der im Repository oder zwischen verschiedenen Versionen:
>cvs diff
Ohne weitere Parameter werden die unterschiede zwischen den Dateien im aktuellen Verzeichnis, und den Dateien im Repository ausgegeben.
Um direkt die Unterschiede zwischen zwei Versionsnummern angezeigen zu lassen, bekommt
diff
die Option
-r
(für Revision) mit auf den Weg:
>cvs diff -r 3.0 -r 3.12 Module
In diesem Beispiel werden die Unterschiede zwischen den Versionen 3.0 und 3.12 ausgegeben.
Was für Versionen funktioniert, geht natürlich auch für Dati:
>cvs diff -D 09/11/2000 -D 09/19/2000 Module
Das Beispiel zeigt Unterschiede zwischen Versionen vom 11.09.2000 und vom 19.09.2000 auf.
(Datum im Format mm/dd/yyyy)
Alle Unterschiede seit dem letzten
checkout
werden von
>cvs diff -u Module
angezeigt.
Führt man vor jedem
commit
ein:
>cvs diff -u Module >>Module.changelog
aus, erhält man mit der Zeit eine Changelog-Datei ohne diese selbst zu bearbeiten zu müssen.
top
3.11 Branches
Erzeugen eines Branches (Ast), der unabhängig vom Haupt-(Datei)-Baum bearbeitbar ist.
Branches können eigenständig bleiben oder später zum Haupt-Baum hinzugefügt werden ("merge"):
Um einen neuen Branch einzufügen verwenden wir folgenden Befehl:
>cvs tag -b branch_tag foo.cpp
Dies erzeugt einen neuen Zweig (Branch) für die Datei
foo.cpp
mit dem Tag
branch_tag
im Repository, ausgehend von der Version, die sich momentan im Arbeitsverzeichnis befindet.
Achtung!! Es wurde nur der Zweig erzeugt. Man arbeitet aber nicht automatisch im neuen Branch!!!
Um mit dem neuen Branch arbeiten zu können müssen wir diesen zuerst in unser Arbeitsverzeichnis holen:
>cvs update -r branch_tag foo.cpp
so ... jetzt haben wir den Branch im Arbeitsverzeichnis, was wir mit einem
>cvs status foo.cpp
überprüfen können.
VARIANTE:
>cvs checkout -d ./test_branch -r branch_tag foo.cpp
Erzeugt ein Verzeichnis test_branch und legt die Dateien in diesem ab. Dadurch kann man mehrere Branches parallel bearbeiten.
Jetzt ist unser Arbeitsverzeichnis auf den neuen Branch eingestellt, und wir können mit einem ganz normalen
>cvs commit foo.cpp
Änderungen in den Branch übernehmen.
top
3.12 Die History
Auslesen der History:
>cvs history -e
gibt alles aus
>cvs history -m {Module}
gibt nur die History dieses Modules aus
>cvs history -c
Info über "commited files"
>cvs history -o
Info über "checked out files"
top
3.13 Exportieren
Um nur die "Nutzdaten" vom 24.12.2002 ohne die Verwaltungsdateien von CVS zu erhalten (in das lokale Verzeichnis
ExportModul
):
>cvs export -d ExportModul -D 12/24/2002 Modul
top
3.14 update
Um die eigene Arbeitsversion einer Datei mit den Änderungen anderer Bearbeiter zu synchronisieren, führt man
cvs update
aus:
>cvs update Doku_CVS
top
3.15 Ignorieren von Dateien
Befinden sich bei einem CVS Update Dateien im lokalen Arbeitsverzeichnis, die nicht von CVS verwaltet werden, ergibt sich eine Meldung wie:
? Doku_CVS//Comment
Um solche Meldung zu verhindern, kann man sich in seinem Homeverzeichnis die Datei
.cvsignore
anlegen. Pro Zeile ein Dateiname, * als Joker.
cvs ignoriert von selbst bereits alle Dateien mit:
.bak .BAK .o .obj CVS RCS core
top
3.16 Kurze Kommandoübersicht
CVS Kommandos mit Syntax :
>cvs import [-m {Kommentar}] {Modulname} {Vendor-Tag} {Revision-Tag}
>cvs checkout [-P] [-r {tag}] {Modulname}
>cvs commit [-r {tag}] [{datei}] [{Modulname}]
>cvs update [-p] [-r] [-A] [{tag}] [{Modulname}]
>cvs tag [-b] [-F] {tag} {Modulname}
>cvs rtag [-b] -r {tag} {Modulname}
>cvs add {datei}
>cvs remove [-f] [-l] [-R] {datei}
>cvs -d {CVSROOT-path} init
>cvs history [-m {Modulname}] [-e] [-o]
>cvs export -d {Verzeichnisname} [-D {Datum}] [-r {tag}]{Modulname}
top
4.1 Beispiele für die Variable CVSROOT
CVSROOT=:pserver:user@cvs.example.org:2402/usr/local/cvsroot
pserver
= die Verbindung zum entfernter CVS-Server soll über TCP/IP aufgebaut werden.
user
= dieser User wird zum login verwendet.
cvs.example.org
Domain oder IP des Rechners am den sich CVS verbinden soll.
2402
Port an den sich CVS verbinden soll. (2401 ist default).
/usr/local/cvsroot
Verzeichnis des Repositories (auf dem CVS-Server)
CVSROOT=/devel/CVSROOT
Es soll das Repository auf der lokalen Platte im Verzeichnis
/devel/CVSROOT
verwendet werden.
top
5.1 Zweites Repository verwenden
Hat man die Variable
$CVSROOT
nicht gesetzt oder will sie nicht ändern, weil sie auf ein weiteres, benutztes Repository verweist, kann mit
>cvs -d 10.0.0.216:/var/CVS checkout alice
der Pfad nach -d übergeben werden. Die Pfadangabe muß absolut sein.
top
5.2 Lokale kopie an ein neues Repository anpassen
Wenn das Repository auf einen anderen Server verschoben wird, muß man normalerweise seine lokale Arbeitskopie neu auschecken, was aber nicht immer gewünscht ist.
Falls (aus welchen Gründen auch immer) das Repository auf einen anderen Server verschoben wurde,
kann man in der lokalen Arbeitskopie keinen Update oder Commit mehr ausführen.
cvs ist so intelligent, das es den Inhalt von
CVSROOT
für jedes Verzeichnis speichert, und bei allen weiteren cvs-operationen als default verwendet.
Das ist prinzipiell wunderbar, denn nur so sind die 'kurzen' cvs Befehle erst möglich.
>cvs update
anstatt
>cvs -d /usr/local/cvsroot update
Falls aber der CVS-Server einen neuen Namen (usw..) bekommen hat, versucht cvs immer sich zum alten Server zu verbinden.
Folgendes script Ersetzt alle alten Einträge mit denen des neuen Servers so das ein komplett neuer checkout nicht mehr notwendig ist:
>cd /das/lokale/arbeitsverzeichnis/
for f in `find . -name "Root"|grep "/CVS/Root"`
do
cat $f|sed -e"s/alter.cvs.server/neuer.cvs.server/" > /tmp/tmpf; mv /tmp/tmpf $f
done
Hinweis:
Das Verzeichnis
/tmp
sollte vorhanden sein.
top
|