Inhalt

1. CVS benutzen -- eine Einführung

Dies ist das Skript zu einem Vortrag, den ich (KaiMoritz) neulich bei der LugEssen hielt.

1.1. Vorbereitungen

Die Befehle in diesem Abschnitt sollte man sich nicht merken. Man benutzt sie in der Regel so selten, daß man sie sowieso jedes mal wieder nachschlagen muß.

1.1.1. Installation

Nicht nötig! Es muß lediglich das Binary auf dem System vorhanden sein.

Ausnahme: cvspserver

1.1.2. Einen CVS-Repository anlegen (init)

Ein Repository wird mit dem folgenden Befehl erzeugt:

fREUNd:/home/kai# cvs -d /var/lib/cvs init
fREUNd:/home/kai#

Oder auch mit:

kai@fREUNd:~$ cvs -d /home/kai/cvsroot init
kai@fREUNd:~$

Danach ist das Repository sofort einsatzbereit. Für die einfache Benutzung ist keine weitere Konfiguration nötig.

Es gibt keine Vorschrift, wo das Repository im Dateisystem abgelegt wird. Da CVS zudem keine zentrale Konfigurationsdatei benutzt, sondern die Konfigurationseinstellungen im Repository speichert, kann man auch als normaler Benutzer auf einem beliebigen System, auf dem man über einen Benutzer-Shell-Account verfügt, sein CVS betreiben und auf diesen auch von anderen Rechnern zugreifen.

1.1.3. Ein Projekt erzeugen (import)

Ein neues Projekt wird mit dem Befehl  import  erzeugt. Dabei kann ein leeres Verzeichnis importiert werden, oder ein gesamter Verzeichnisbaum eines bestehenden Projektes.

Mit dem folgendem Befehl wird das Verzeichnis  xpenguins-1.2  in das eben angelegten Repository  /home/kai/cvsroot  importiert und dort unter dem Namen  xpenguins  abgelegt. Mit  -m  wird eine Log-Meldung erzeugt (wird  -m  weggelassen, holt sich CVS die Log-Meldung, indem es einen Editor öffnet).  foo  ist ein vendor-tag (dessen Nutzen mir schleierhaft ist).  frisch_importiert  ist ein release-tag, über das man später auf diese Version der Quellen zugreifen kann.

kai@fREUNd:~/xpenguins-1.2$ cvs -d /home/kai/cvsroot/ import -m "xpenguins-Quellcode importiert" xpenguins foo frisch_importiert
N xpenguins/toon.c
N xpenguins/toon.h
N xpenguins/xpenguins.c
N xpenguins/AUTHORS
N xpenguins/vroot.h
N xpenguins/COPYING
N xpenguins/INSTALL
N xpenguins/Makefile
N xpenguins/README
N xpenguins/xpenguins.1
N xpenguins/ChangeLog
I xpenguins/xpenguins.o
I xpenguins/toon.o
N xpenguins/xpenguins
N xpenguins/penguins/bomber.xpm
N xpenguins/penguins/climber.xpm
N xpenguins/penguins/def.h
N xpenguins/penguins/explosion.xpm
N xpenguins/penguins/faller.xpm
N xpenguins/penguins/floater.xpm
N xpenguins/penguins/tumbler.xpm
N xpenguins/penguins/walker.xpm

No conflicts created by this import

kai@fREUNd:~/xpenguins-1.2$

Wie man sieht ist CVS sogar schlau genug  *.o  -Dateien nicht mitzuimportieren.

Wichtig: Durch den  import  -Befehl wird an dem Verzeichnis nichts geändert!

1.2. Erste Schritte

1.2.1. Ein Projekt auschecken (checkout)

Bevor an einem CVS-Projekt gearbeitet werden kann, muß es ausgecheckt werden. Eine Bearbeitung direkt im Repository ist nicht möglich (bzw. sinnvoll).

Ein Projekt wird mit dem Befehl  checkout  oder kurz  co  ausgecheckt. Dabei muß mit dem Schalter  -d  angegeben werden, welches CVS-Repository benutzt werden soll.

kai@fREUNd:~$ cvs -d /home/kai/cvsroot/ co xpenguins
cvs checkout: Updating xpenguins
U xpenguins/AUTHORS
U xpenguins/COPYING
U xpenguins/ChangeLog
U xpenguins/INSTALL
U xpenguins/Makefile
U xpenguins/README
U xpenguins/toon.c
U xpenguins/toon.h
U xpenguins/vroot.h
U xpenguins/xpenguins
U xpenguins/xpenguins.1
U xpenguins/xpenguins.c
cvs checkout: Updating xpenguins/penguins
U xpenguins/penguins/bomber.xpm
U xpenguins/penguins/climber.xpm
U xpenguins/penguins/def.h
U xpenguins/penguins/explosion.xpm
U xpenguins/penguins/faller.xpm
U xpenguins/penguins/floater.xpm
U xpenguins/penguins/tumbler.xpm
U xpenguins/penguins/walker.xpm

Anstelle von  -d /home/kai/cvsroot  kann auch die Umgebungsvariable  CVSROOT  gesetzt werden. Dies ist jedoch nicht unbedingt nötig, da CVS in dem ausgecheckten Verzeichnisbaum speichert, welches Repository genutzt wird. D.h. wenn man sich in einem ausgecheckten Verzeichnis befindet ist die Angabe von  -d /home/kai/cvsroot  sowieso nicht mehr nötig.

Zu beachten: CVS beachtet Dateirechte, Benutzer und Gruppen nicht!

1.2.2. Zugriff auf fremde Quellen (login und checkout)

Wenn man anstatt auf ein lokales auf ein entferntes Repository zugreifen will, ändert sich eigentlich fast nichts. Lediglich beim  checkout  der Arbeitskopie müssen ein paar andere Schalter betätigt werden. Danach speichert CVS die Zugriffsmethode in der Arbeitskopie. D.h. wenn man sich in dem Dateibaum der Arbeitskopie befindet, muß man den Schalter  -d  nicht mehr angeben.

1.2.2.1. Zugriff per SSH

Um per ssh auf ein entferntes Repository zuzugreifen, muß zunächst in der Umgebungsvariable  CVS_RSH  gespeichert werden, welches Remote-Shell Programm benutzt werden soll.

kai@fREUNd:~$ export CVS_RSH=ssh
kai@fREUNd:~$

Danach muß beim  checkout  wieder der Schalter  -d  betätigt werden.

kai@fREUNd:~$ cvs -d :ext:kai@bRUDEr:/var/lib/cvs co cvs
cvs server: Updating cvs
U cvs/background.png
U cvs/ersteschritte.html
U cvs/fortsetzung.html
U cvs/index.html
U cvs/muster.html
U cvs/quellen.html
U cvs/stolperfallen.html
U cvs/timemachine-klein.png
U cvs/timemachine.png
U cvs/vorbereitungen.html
U cvs/vortrag.css
U cvs/weiterlaufen.html
U cvs/wettrennen.html
kai@fREUNd:~$

Die allgemeine Syntax von  -d  ist:  :ZUGRIFFSMETHODE:BENUTZER@RECHNER:PFAD_ZUM_CVSVERZEICHNIS  .  ext  steht hier dafür, daß ein externes Programm für die Verbindung benutzt werden soll. Welches ist in  CVS_RSH  gespeichert. Weiter sieht man: ich greife als Benutzer  kai  auf den Rechner  bRUDEr  auf das Repository  /var/lib/cvs  zu.

Um diese Zugriffsmethode zu aktivieren, sind keine Root-Rechte notwendig. Die einzige Voraussetzung ist, dass sich das CVS-Binary im Pfad des Remote-Shell-Accounts befindet. D.h. man kann auf einem beliebigen Rechner, auf dem man einen Account besitzt, in seinem Home-Verzeichnis ein CVS-Repository anlegen und auf dieses Repository von anderen Rechnern aus zugreifen.

Wie die Authentifizierung abläuft, bestimmt dabei das Programm, das in  CVS_RSH  angegeben wurde. (In meinem Fall war keine Passworteingabe nötig, da ich für diesen Rechner einen SSH-Schlüssel ohne Mantra benutze... bequem, aber eine gewisse Sicherheitslücke.)

1.2.2.2. Zugriff per pserver

Bei dem Zugriff über einen pserver, der natürlich auf dem Remote-Rechner entsprechend eingerichtet worden sein muß, ist zunächst eine Authentifizierung per  login  notwendig. Danach kann die Arbeitskopie ausgecheckt werden. CVS legt die Zugriffsmethode (und in diesem Fall auch das Passwort) wieder in der Arbeitskopie ab, so daß nach dem  checkout  die Zugriffsmethode wiederum nicht mehr angegeben werden muß. Als  ZUGRIFFSMETHODE  muß dieses mal  pserver  gewählt werden.

kai@fREUNd:~$ cvs -d :pserver:anonymous@anoncvs.kde.org:/home/kde login
Logging in to :pserver:anonymous@anoncvs.kde.org:2401/home/kde
CVS password:
kai@fREUNd:~$ cvs -d :pserver:anonymous@anoncvs.kde.org:/home/kde co kdepim/kpilot
cvs server: Updating kdepim/kpilot
U kdepim/kpilot/.cvsignore
U kdepim/kpilot/AUTHORS
U kdepim/kpilot/COPYING
U kdepim/kpilot/ChangeLog
U kdepim/kpilot/INSTALL

[...]

U kdepim/kpilot/lib/syncAction.cc
U kdepim/kpilot/lib/syncAction.h
U kdepim/kpilot/lib/uiDialog.cc
U kdepim/kpilot/lib/uiDialog.h
cvs server: Updating kdepim/kpilot/po
cvs server: Updating kdepim/kpilot/po/en
cvs server: Updating kdepim/kpilot/po/nl
kai@fREUNd:~$

Das Passwort ist hier natürlich von dem pserver abhängig, den man benutzt. Bei anonymem Zugriff ist es aber in der Regel leer (  RETURN  ). Im zweiten Schritt muß hier noch mal  -d ...  mit angegeben werden, da zu diesem Zeitpunkt noch nichts ausgecheckt wurde, also noch keine Arbeitskopie existiert, in der CVS die Zugriffsmethode abgespeichert haben könnte.

1.2.3. Was habe ich bloß getan?? (update und diff)

Nachdem man eine Weile an dem Code herumgefummelt hat, fragt man sich meistens, was man überhaupt alles gemacht hat. Dies erfährt man von CVS mit dem Kommando  update  (wie der Name ahnen läßt, macht dieses Komando noch mehr).

Das Komando arbeitet - wie alle CVS-Komandos - auf allen Dateien im aktuellen Verzeichnis und steigt auch in untergeordnete Verzeichnisse ab.

kai@fREUNd:~$ cd xpenguins/
kai@fREUNd:~/xpenguins$ echo "Ich war hier..." >> README
kai@fREUNd:~/xpenguins$ echo "/* Sinnloser Text */" >> xpenguins.c
kai@fREUNd:~/xpenguins$ echo "/* Sinnloser Text */" >> penguins/def.h
kai@fREUNd:~/xpenguins$ cvs up
cvs update: Updating .
M README
M xpenguins.c
cvs update: Updating penguins
M penguins/def.h
kai@fREUNd:~/xpenguins$

Wie man sieht ist der Schalter  -p  nicht mehr nötig, da wir uns nun in einem ausgecheckten Verzeichnis befinden.

Genauere Informationen kann man sich mit dem Komando  diff  anzeigen lassen. Auch dieses Komando arbeitet ohne weitere Angaben auf allen Dateien im aktuellen Verzeichnis und den Verzeichnissen, die diesem untergeordnet sind. Wenn man nur über eine Datei (oder mehrere bestimmte Dateien) genau wissen will, was man verändert hat, gibt man diese einfach an. Hier ein Aufruf für ein diff der Änderungen an der Datei  README  :

kai@fREUNd:~/xpenguins$ cvs diff README
Index: README
===================================================================
RCS file: /home/kai/cvsroot/xpenguins/README,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 README
62a63
> Ich war hier...
kai@fREUNd:~/xpenguins$

Das CVS-  diff  versteht die üblichen diff-Schalter. Hier ein Aufruf mit  -c  ohne Angabe eines bestimmten Files. Es werden also die diffs gegen alle veränderten Dateien angezeigt:

kai@fREUNd:~/xpenguins$ cvs diff -c
cvs diff: Diffing .
Index: README
===================================================================
RCS file: /home/kai/cvsroot/xpenguins/README,v
retrieving revision 1.1.1.1
diff -c -c -r1.1.1.1 README
*** README      9 May 2003 17:34:47 -0000       1.1.1.1
--- README      9 May 2003 21:20:31 -0000
***************
*** 60,62 ****
--- 60,63 ----
  Microsoft Windows and called it `WinPenguins' - visit:
        http://neomueller.org/~isamu/winpenguins/

+ Ich war hier...
Index: xpenguins.c
===================================================================
RCS file: /home/kai/cvsroot/xpenguins/xpenguins.c,v
retrieving revision 1.1.1.1
diff -c -c -r1.1.1.1 xpenguins.c
*** xpenguins.c 9 May 2003 17:34:47 -0000       1.1.1.1
--- xpenguins.c 9 May 2003 21:20:40 -0000
***************
*** 423,425 ****
--- 423,426 ----
     exit(0);
  }

+ /* Sinnloser Text */
cvs diff: Diffing penguins
Index: penguins/def.h
===================================================================
RCS file: /home/kai/cvsroot/xpenguins/penguins/def.h,v
retrieving revision 1.1.1.1
diff -c -c -r1.1.1.1 def.h
*** penguins/def.h      9 May 2003 17:34:47 -0000       1.1.1.1
--- penguins/def.h      9 May 2003 21:20:44 -0000
***************
*** 50,52 ****
--- 50,53 ----
     { bomber_xpm, 16, 1, 32, 32, TOON_NOCYCLE },
     { explosion_xpm, 1, 1, 64, 64, TOON_NOCYCLE }
  };
+ /* Sinnloser Text */
kai@fREUNd:~/xpenguins$

1.2.4. Änderungen verwerfen (update)

Stellt man nun fest, dass die Änderungen an der Datei  README  eigentlich doch überflüssig sind, so kann man diese einfach verwerfen, indem man die Datei löscht und sich nachher per  cvs up  die alte Version wiederholt:

kai@fREUNd:~/xpenguins$ rm README
kai@fREUNd:~/xpenguins$ cvs up
cvs update: Updating .
cvs update: warning: README was lost
U README
M xpenguins.c
cvs update: Updating penguins
M penguins/def.h
kai@fREUNd:~/xpenguins$

Das  U  vor der Datei  README  zeigt an, daß diese neu aus dem Repository geholt wurde. Das  M  vor  xpenguins/def.h  zeigt an, daß hier weiterhin Änderungen in unserer Arbeitskopie des Projektes vorhanden sind, die noch nicht in das Repository übertragen wurden.

1.2.5. Änderungen in das Repository übertragen (checkin)

Nachdem wir uns nun versichert haben, daß alle vorgenommenen Änderungen sinnvoll sind, sollen diese in das Repository übertragen werden. Dies leistet das Komando  commit  oder kurz  ci  . Auch dieses Kommando kann ohne weitere Angaben aufgerufen werden, um alle Änderungen in das Repository zu übertragen, oder mit einer Liste von Dateien, wenn nur bestimmte Änderungen übertragen werden sollen.

kai@fREUNd:~/xpenguins$ cvs ci -m "Mehr oder weniger sinnige Änderungen"
cvs commit: Examining .
cvs commit: Examining penguins
Checking in xpenguins.c;
/home/kai/cvsroot/xpenguins/xpenguins.c,v  <--  xpenguins.c
new revision: 1.2; previous revision: 1.1
done
Checking in penguins/def.h;
/home/kai/cvsroot/xpenguins/penguins/def.h,v  <--  def.h
new revision: 1.2; previous revision: 1.1
done
kai@fREUNd:~/xpenguins$

CVS teilt mit, daß nun in dem Repository neben der vorhergehenden (initialen) Version 1.1 für die beiden Dateien eine neue Version 1.2 erzeugt wurde.

Ohne Angabe von  -m "Mehr oder weniger sinnige Änderungen"  würde der Standard-Editor geöffnet, um eine Checkin-Lognachricht zu erfragen. Dies sieht dann z.B. so aus:

CVS: ------------------------------------------------------------------
CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
CVS:
CVS: Committing in .
CVS:
CVS: Modified Files:
CVS:    README toon.h
CVS: Added Files:
CVS:    LIESMICH
CVS: ------------------------------------------------------------------
~
~
~
~
                                                      1,0-1         All

CVS listet in einem auskommentierten Bereich die Dateien auf, die durch den Checkin geändert, hinzugefügt oder gelöscht werden. Es lohnt sich, nicht einfach alle Dateien einzuchecken, sondern immer die Dateien gemeinsam, deren Änderungen inhaltlich zusammenhängen. Dann kann man bequem die Kommentarzeichen (  CVS:  ) vor den Zeilen entfernen, die die Änderungen auflisten, und braucht nur noch eine Textnachricht zu ergänzen.

Achtung: Gute Checkin-Logs zu schreiben macht zwar Arbeit, aber auch unheimlich viel Sinn. Sie können später bei der gewissenhaften Vorbereitung einer Zeitreise von unschätzbarem Wert sein!

1.2.6. Eine neue Datei hinzufügen (add)

Wie fügt man nun eine neue Datei zu einem Projekt hinzu? Erzeugen wir zunächst die Datei und fragen CVS mit dem Kommando  update , was es von dieser Datei weiß:

kai@fREUNd:~/xpenguins$ echo "Dies ist der Inhalt" > neu.txt
kai@fREUNd:~/xpenguins$ cvs up
cvs update: Updating .
? neu.txt
cvs update: Updating penguins
kai@fREUNd:~/xpenguins$

Wie man sieht, weiß CVS konsequenterweise nichts mit unserer neuen Datei anzufangen. Wir müssen CVS also mitteilen, daß wir eine neue Datei erzeugt haben. Dies geschieht mit dem Kommando  add  :

kai@fREUNd:~/xpenguins$ cvs add neu.txt
cvs add: scheduling file `neu.txt' for addition
cvs add: use 'cvs commit' to add this file permanently
kai@fREUNd:~/xpenguins$

CVS weist uns darauf hin, daß wir das Kommando  commit  benutzen müssen, um unsere neue Datei wirklich in das Repository aufzunehmen. Was hat das zu bedeuten?

Das  add  -Kommando arbeitet nur auf der Arbeitskopie des Projektes. D.h. es vermerkt in einer der Dateien, die in dem Verzeichnis  CVS  zu finden sind, daß unsere neue Datei beim nächsten Aufruf von  commit  in das Repository übertragen werden soll. An dem Repository verändert unser Aufruf von  cvs add  also nichts! Wenn wir die neue Datei löschen, bevor wir  cvs ci  aufrufen, ist sie unwiederbringlich verloren!

kai@fREUNd:~/xpenguins$ cvs ci -m "Neue Datei hinzugefügt"
cvs commit: Examining .
cvs commit: Examining penguins
RCS file: /home/kai/cvsroot/xpenguins/neu.txt,v
done
Checking in neu.txt;
/home/kai/cvsroot/xpenguins/neu.txt,v  <--  neu.txt
initial revision: 1.1
done
kai@fREUNd:~/xpenguins$

Jetzt erst wurde die Datei in das Repository übertragen und erhält die initiale Version 1.1.

1.2.7. Eine Datei entfernen (rm)

Oben haben wir bereits gesehen, daß eine gelöschte Datei durch den nächsten Aufruf von  cvs up  wiederhergestellt wird. Auch um Dateien aus einem Projekt zu löschen sind also mehrere Schritte nötig:

Um die Datei  neu.txt  wieder zu löschen müssen also folgende Schritte durchgeführt werden:

kai@fREUNd:~/xpenguins$ rm neu.txt
kai@fREUNd:~/xpenguins$ cvs rm neu.txt
cvs remove: scheduling `neu.txt' for removal
cvs remove: use 'cvs commit' to remove this file permanently
kai@fREUNd:~/xpenguins$ cvs ci -m "Datei neu.txt wieder gelöscht."
cvs commit: Examining .
cvs commit: Examining penguins
Removing neu.txt;
/home/kai/cvsroot/xpenguins/neu.txt,v  <--  neu.txt
new revision: delete; previous revision: 1.1
done
kai@fREUNd:~/xpenguins$

1.2.8. Das ist doch alles viel zu umständlich, oder?

NEIN!

Auf den ersten Blick mag z.B. das Löschen oder Hinzufügen von Dateien zu einem CVS-Projekt etwas umständlich erscheinen. Ein paar Worte zum Konzept von CVS sollen daher klarstellen, daß es sich hier nicht um einen Design-Fehler handelt, sondern um eine konsequente Implementation der gewünschten Funktion.

CVS trennt scharf zwischen dem Repository und der Arbeitskopie, die sich ein Benutzer aus diesem Repository besorgt hat. Für den Benutzer ist immer nur seine Arbeitskopie zugänglich. Änderungen die er hier vornimmt, bleiben lokal, bis er sie explizit per  checkin  an das Repository überträgt. Dies hat mehrere entscheidende Vorteile:

Um diese Vorteile zu erreichen kann CVS natürlich nicht einfach irgendwelche Dateien im Repository löschen oder erzeugen, wenn der Benutzer dies in seiner Arbeitskopie tut. CVS kann ja nicht unterscheiden, ob diese Änderungen aus der Sicht des Benutzers sinnvoll und dauerhaft sind, oder bloß experimentellen Charakter haben.

1.3. Weiterlaufen

1.3.1. In Geschichtsbüchern schmökern (log)

Wie gezeigt wurde (vgl. Was habe ich bloß getan??) kann man mit  cvs diff  die Änderungen seit dem letzten  commit  anzeigen. Doch es sind nicht immer nur die Änderungen interessant, die man gerade gemacht hat. Eventuell möchte man mal alle Änderungen angezeigt bekommen, die man in mehreren Schritten gemacht hat, seit man sich z.B. zu einer grundlegenden Änderung an einem Projekt entschlossen hat.

Zu diesem Zweck muß man zunächst herausfinden, auf welchen Punkt in der Vergangenheit man sich beziehen möchte. Man kann seine Zeitmaschine ja nicht einfach so anschmeißen, wer weiß, wo man dann landen würde! Hier hilft das CVS-Kommando  log  . Es zeigt die Log-Nachrichten an, die beim Checkin der Änderungen angegeben wurden, zusammen mit dem Datum des Checkins und den Namen des Benutzers, der die Änderungen übertragen hat.

kai@fREUNd:~/xpenguins$ cvs log README

RCS file: /home/kai/cvsroot/xpenguins/README,v
Working file: README
head: 1.4
branch:
locks: strict
access list:
symbolic names:
        frisch_importiert: 1.1.1.1
        foo: 1.1.1
keyword substitution: kv
total revisions: 5;     selected revisions: 5
description:
----------------------------
revision 1.4
date: 2003/05/12 19:52:38;  author: kai;  state: Exp;  lines: +0 -2
tach-Zeile wieder entfernt...

 Modified Files:
        README
----------------------------
revision 1.3
date: 2003/05/12 19:52:09;  author: kai;  state: Exp;  lines: +0 -6
Ich will keinen Hinweis auf Software für M$
 Modified Files:
        README
----------------------------
revision 1.2
date: 2003/05/12 19:36:58;  author: kai;  state: Exp;  lines: +1 -11
Wilde Entwicklungsphase erfolgreich abgeschlossen!

 Modified Files:
        README toon.h
 Added Files:
        LIESMICH
----------------------------
revision 1.1
date: 2003/05/09 17:34:47;  author: kai;  state: Exp;
branches:  1.1.1;
Initial revision
----------------------------
revision 1.1.1.1
date: 2003/05/09 17:34:47;  author: kai;  state: Exp;  lines: +0 -0
xpenguins-Quellcode importiert
===================================================================
kai@fREUNd:~/xpenguins$

1.3.2. "Früher war alles anders!" Herausfinden, was sich wirklich verändert hat. (diff -r)

Aus dem Log für die Datei  README  mag nun das Interesse erwachsen, herauszufinden, was man an der Datei seit dem Ende der "wilden Entwicklungsphase" so alles geändert hat. Dies läßt sich mit folgendem  diff  -Aufruf herausfinden:

kai@fREUNd:~/xpenguins$ cvs diff -c -r 1.2 README
Index: README
===================================================================
RCS file: /home/kai/cvsroot/xpenguins/README,v
retrieving revision 1.2
retrieving revision 1.4
diff -c -r1.2 -r1.4
*** README      12 May 2003 19:36:58 -0000      1.2
--- README      12 May 2003 19:52:38 -0000      1.4
***************
*** 42,52 ****
  The xpenguins homepage is  located at:
        http://www.met.rdg.ac.uk/~swrhgnrj/xpenguins/

-
- SEE ALSO
-
- Michael Vines <isamu@neomueller.org> has rewritten the program for
- Microsoft Windows and called it `WinPenguins' - visit:
-       http://neomueller.org/~isamu/winpenguins/
-
- tach
--- 42,44 ----
kai@fREUNd:~/xpenguins$

Der Schalter  -r  gibt an, dass ein Diff gegen die Version  1.2  der Datei hergestellt werden soll. Zu beachten ist dabei, daß ein Diff der Datei, wie sie sich derzeit im Arbeitsverzeichnis befindet, gegen die Version  1.2  gemacht wird. In dem Beispiel war die Datei auf dem aktuellen Stand. Deswegen wurde direkt ein  diff  der beiden Versionen  1.2  und  1.4  durchgeführt. Hätte man seit dem letzten Checkin weitere Änderungen an der Datei vorgenommen, so wäre ein  diff  gegen die veränderte Version im Arbeitsverzeichnis gemacht worden:

kai@fREUNd:~/xpenguins$ echo Neue Zeile >> README
kai@fREUNd:~/xpenguins$ cvs diff -c -r1.2 README
Index: README
===================================================================
RCS file: /home/kai/cvsroot/xpenguins/README,v
retrieving revision 1.2
diff -c -r1.2 README
*** README      12 May 2003 19:36:58 -0000      1.2
--- README      17 May 2003 11:20:58 -0000
***************
*** 42,52 ****
  The xpenguins homepage is  located at:
        http://www.met.rdg.ac.uk/~swrhgnrj/xpenguins/

!
! SEE ALSO
!
! Michael Vines <isamu@neomueller.org> has rewritten the program for
! Microsoft Windows and called it `WinPenguins' - visit:
!       http://neomueller.org/~isamu/winpenguins/
!
! tach
--- 42,45 ----
  The xpenguins homepage is  located at:
        http://www.met.rdg.ac.uk/~swrhgnrj/xpenguins/

! Neue Zeile
kai@fREUNd:~/xpenguins$

Zu Begin weist CVS explizit darauf hin, welche Versionen gedifft werden.

diff -c -r1.2 README
*** README      12 May 2003 19:36:58 -0000      1.2
--- README      17 May 2003 11:20:58 -0000

Hier sieht man daran, daß in der letzten Zeile keine Versions-Nummer genannt wird, daß die Datei-Version  1.2  gegen die Datei-Version im Arbeitsverzeichnis gedifft wird, die noch nicht ins Repository übertragen wurde.

Möchte man explizit zwei bestimmte Versionen der Datei überprüfen, die bereits im Repository gespeichert sind, so kann man dies über zweimaliges verwenden des Schalters  -r  erreichen. Z.B. kann man sich mit folgendem Aufruf davon überzeugen, daß der Log-Eintrag für die Version  1.3  die eingecheckten Veränderungen ausreichend umschreibt:

kai@fREUNd:~/xpenguins$ cvs diff -c -r 1.2 -r1.3 README
Index: README
===================================================================
RCS file: /home/kai/cvsroot/xpenguins/README,v
retrieving revision 1.2
retrieving revision 1.3
diff -c -r1.2 -r1.3
*** README      12 May 2003 19:36:58 -0000      1.2
--- README      12 May 2003 19:52:09 -0000      1.3
***************
*** 43,52 ****
        http://www.met.rdg.ac.uk/~swrhgnrj/xpenguins/


- SEE ALSO
-
- Michael Vines <isamu@neomueller.org> has rewritten the program for
- Microsoft Windows and called it `WinPenguins' - visit:
-       http://neomueller.org/~isamu/winpenguins/
-
tach
--- 43,46 ----
kai@fREUNd:~/xpenguins$

1.3.3. "Weißt du noch, damals... !" Alte Versionen betrachten (up -p -r)

Manchmal ist es vielleicht etwas verwirrend, nur die Unterschiede zwischen zwei Dateiversionen zu sehen und man möchte viel lieber einfach eine alte Version der Datei betrachten. Dies erreicht man mit folgendem Aufruf:

kai@fREUNd:~/xpenguins$ cvs up -p -r 1.3 README |less

Der Schalter  -p  erzwingt dabei, daß die Datei auf  STDOUT  ausgegeben wird. Der Befehl  cvs up  kombiniert mit dem Schalter  -r  versetzt nämlich eigentlich die Arbeitskopie in einen vergangenen Zustand zurück. Dazu nun mehr.

1.3.4. "Früher war es viel schöner!" Eine erste Zeitreise (up -r)

Wie gesagt ersetzt  cvs up -r VERSIONSNR  eine Datei in der Arbeitskopie mit der geforderten Version. Wenn man wirklich die alte Version der Datei haben will, ist darauf zu achten, daß die Datei in der Arbeitskopie nicht verändert wurde, denn sonst führt CVS die aktuelle und die angeforderte Version zu einer neuen Datei zusammen (was unter bestimmten Umständen natürlich durchaus gewünscht sein kann)!

kai@fREUNd:~/xpenguins$ cvs up -r1.1 penguins/def.h
U penguins/def.h
kai@fREUNd:~/xpenguins$

Die Anforderung einer alten Datei-Version per  cvs up -r  ist aber nicht unbedingt das, was man sich als CVS-Neuling darunter vorstellt. Diese alte Version kann nämlich (frei nach dem Motto, daß man als Zeitreisender nichts an der Vergangenheit verändern sollte) nicht verändert werden!

kai@fREUNd:~/xpenguins$ echo "Änderung der Vergangenheit" >> penguins/def.h
kai@fREUNd:~/xpenguins$ cvs ci penguins/def.h
cvs commit: sticky tag `1.1' for file `penguins/def.h' is not a branch
cvs [commit aborted]: correct above errors first!
kai@fREUNd:~/xpenguins$

Die obige Fehlermeldung besagt, daß man, wenn man wirklich eine alte Version der Datei verändern will, zunächst einen  Branch  (im Fachjargon des Zeitreisenden: ein Parallel-Universum) erzeugen muß.

Oft ist das aber gar nicht, was man als CVS-Neuling wirklich will. Eigentlich will man meistens nur in der Gegenwart mit einer alten Version der Datei weiterarbeiten, weil man festgestellt hat, daß die Änderungen, die man vorgenommen hatte, Blödsinn sind. Kurz: man will einfach ein paar Änderungen rückgängig machen. Dies erreicht man mit folgendem Befehl:

kai@fREUNd:~/xpenguins$ cvs up -p -r1.1 README > README
===================================================================
Checking out README
RCS:  /home/kai/cvsroot/xpenguins/README,v
VERS: 1.1
***************
kai@fREUNd:~/xpenguins$

Das Resultat dieses Befehls ist, daß die Datei README den selben Inhalt hat, wie die Version  1.1  im Repository. Der Unterschied zu dem vorherigen Befehl ist, dass CVS nicht weiß, woher diese Änderungen an der Datei kommen. Für CVS könnten sie ebensogut von dem Benutzer per Hand eingegeben worden sein.

Aber woher weiß CVS, daß die Änderungen an der Datei  penguins/def.h  nach dem Aufruf ohne  -p  nicht vom Benutzer stammen?

1.3.5. Eine klebrige Angelegenheit: Sticky Tags (status)

Die Antwort lautet:  Sticky Tags  . CVS speichert für jede Datei der Arbeitskopie ein paar wesentliche Informationen (in der Datei  ./CVS/Entries  ). Diese können per  cvs status  oder kurz  cvs stat  abgefragt werden.

kai@fREUNd:~/xpenguins$ cvs stat penguins/def.h README
===================================================================
File: def.h             Status: Locally Modified

   Working revision:    1.1     Sat May 17 12:51:27 2003
   Repository revision: 1.1     /home/kai/cvsroot/xpenguins/penguins/def.h,v
   Sticky Tag:          1.1
   Sticky Date:         (none)
   Sticky Options:      (none)

===================================================================
File: README            Status: Locally Modified

   Working revision:    1.4     Sat May 17 14:16:20 2003
   Repository revision: 1.4     /home/kai/cvsroot/xpenguins/README,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)

kai@fREUNd:~/xpenguins$

Man sieht hier, daß CVS sich für die Datei  penguins/def.h  mit Hilfe des  Sticky Tag  gemerkt hat, daß diese in der Version  1.1  vorliegen soll. Dies ist nötig, da CVS sonst beim nächsten Aufruf von  cvs up  feststellen würde, daß die Version  1.1  , in der die Datei vorliegt, veraltet ist, und dann die neuste Version aus dem Repository holen würde.

Im Fall der Datei  README  , die wir mit  cvs up -p  geholt haben, ist dies nicht nötig, da CVS davon ausgeht, daß wir die neuste Version in unserem Arbeitsverzeichnis haben.

Aber wie wird man ein solches  Sticky Tag  wieder los?

1.3.6. Hände waschen! (cvs up -A)

Ein  Sticky Tag  kann mit dem Aufruf  cvs up -A  gelöscht werden (Vorsicht: der Aufruf arbeitet ohne Dateiangabe wie bei CVS üblich rekursiv das aktuelle Arbeitsverzeichnis und alle untergeordneten Verzeichnisse mit ab!). Dabei ist aber darauf zu achten, daß CVS nicht nur das  Sticky Tag  löscht, sondern die Datei gleichzeitig wieder auf die aktuellste Version bringt. Eventuelle lokale Änderungen werden dabei mit in die neue Version übernommen! Dies kann zu unerwünschten Nebeneffekten führen. Man sollte dem  Sticky Tag  also mit dem Schalter  -p  aus dem Weg gehen, wenn man es nicht explizit haben will!

kai@fREUNd:~/xpenguins$ cvs up -A penguins/def.h
RCS file: /home/kai/cvsroot/xpenguins/penguins/def.h,v
retrieving revision 1.1
retrieving revision 1.2
Merging differences between 1.1 and 1.2 into def.h
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in penguins/def.h
C penguins/def.h
kai@fREUNd:~/xpenguins$

In unserem Fall führt das Löschen des  Sticky Tag  zu einem Konflikt zwischen der Änderung, die wir an der alten Version der Datei vornehmen wollten und der Änderung an dieser alten Version, die wir bereits in das Repository übertragen hatten.

kai@fREUNd:~/xpenguins$ cvs stat penguins/def.h
===================================================================
File: def.h             Status: File had conflicts on merge

   Working revision:    1.2     Result of merge
   Repository revision: 1.2     /home/kai/cvsroot/xpenguins/penguins/def.h,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)

kai@fREUNd:~/xpenguins$ tail penguins/def.h
   { floater_xpm, 8, 1, 30, 30, TOON_DEFAULTS },
   { climber_xpm, 8, 2, 30, 30, TOON_DEFAULTS },
   { bomber_xpm, 16, 1, 32, 32, TOON_NOCYCLE },
   { explosion_xpm, 1, 1, 64, 64, TOON_NOCYCLE }
};
<<<<<<< def.h
Änderung der Vergangenheit
=======
/* Sinnloser Text */
>>>>>>> 1.2
kai@fREUNd:~/xpenguins$

Dies leitet zum nächsten Thema über: Konflikte.

1.4. Wettrennen

1.4.1. CVS: eine wundervolle (Zeit-)Maschine, aber keine Wunder-Maschine

Das Haupteinsatzgebiet von CVS ist die Verwaltung von Programmierprojekten, an denen mehrere Entwickler gemeinsam arbeiten. Auf dem Status von CVS als Quasi-Standard in diesem Bereich basiert ein weit verbreiteter Irrglaube. Dieser besagt, daß man nur CVS aufsetzen muß und sich danach nie mehr Sorgen darum machen muß, wer gerade was bearbeitet, weil es durch den Einsatz von CVS nicht mehr zu Konflikten durch gleichzeitige Bearbeitung einer Datei von mehreren Entwicklern kommen könne. Diese Vorstellung ist bestenfalls eine Halbwahrheit.

Der wichtigste Merksatz beim Umgang mit CVS ist, daß CVS nur helfen kann, Konflikte zu vermeiden bzw. zu beseitigen. CVS kann nicht verhindern, daß bei der gemeinsamen Arbeit mehrerer Entwickler an einem Quellbaum Konflikte entstehen. Dies kann nur durch hinreichende Absprache der Entwickler erreicht werden.

(CVS stellt allerdings Hilfsmittel zur Automatisierung dieser Absprache zur Verfügung:  watch  ,  use  und  edit  . Dieses Thema wird hier aber nicht mehr behandelt...) CVS ist zwar eine wundersame Zeitmaschine, aber eben keine Wundermaschine! Damit ist gemeint:

CVS weiß nichts über den Sinn der Dateien, die es behandelt. Es kennt nur die Unterschiede zwischen den verschiedenen Versionen der Dateien.

Was macht CVS also, wenn es konkurrierende Änderungen an einer Datei feststellt? Es versucht einfach, die unterschiedlichen Änderungen zu einer neuen Version der Datei zusammenzuführen.

1.4.2. Von der Konkurrenz überholt

Wie sieht das nun in der Praxis aus?

Nehmen wir an, wir haben eine Datei lokal verändert und wollen diese Änderungen nun einchecken. Hinter unserem Rücken hat aber ein anderer Benutzer eine Änderung an der selben Datei vorgenommen und diese Änderungen in das Repository eingefügt. Was zunächst passiert ist folgendes:

kai@fREUNd:~/xpenguins$ echo "/* Änderungen... */" >> xpenguins.c
kai@fREUNd:~/xpenguins$ cvs ci xpenguins.c
cvs commit: Up-to-date check failed for `xpenguins.c'
cvs [commit aborted]: correct above errors first!
kai@fREUNd:~/xpenguins$

Welche Fehler meint CVS bloß? Fragen wir CVS doch einfach, was es über den Status der Datei denkt:

kai@fREUNd:~/xpenguins$ cvs stat xpenguins.c
===================================================================
File: xpenguins.c       Status: Needs Merge

   Working revision:    1.3     Sun May 25 16:55:38 2003
   Repository revision: 1.4     /home/kai/cvsroot/xpenguins/xpenguins.c,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)

kai@fREUNd:~/xpenguins$

Ach so! Die Version von  xpenguins.c  in unserem Arbeitsverzeichnis ist nicht auf dem neusten Stand. Sie benötigt eine Zusammenführung mit der Dateiversion im Repository (  Status: Needs Merge  ). CVS besteht also darauf, daß wir uns die neuesten Änderungen aus dem Repository holen, bevor es unsere Änderungen an der Datei akzeptiert. So wird verhindert, daß wir einfach ungewollt die Änderungen des anderen Benutzers rückgängig machen, indem wir unsere ältere Dateiversion, an der wir unsere Änderungen vorgenommen haben, einchecken. (Es wird allerdings nicht verhindert, daß wir einfach die Änderungen des anderen Benutzers nach dem merge von Hand wieder rückgängig machen und dann einchecken, ob das nun Sinn macht, oder nicht -- CVS kann nur verhindern, daß Änderungen anderer aus versehen rückgängig gemacht werden.)

1.4.3. Zurück auf den Stand der Zeit

Um die Datei wieder up-to-date zu bringen, wird natürlich das CVS-Kommando  update  benutzt. Zuvor sollte allerdings überprüft werden, ob sich die Änderungen des anderen Benutzers mit den unsrigen vertragen, oder ob es notwendig ist, das wir uns mit diesem einigen, welche Änderungen zu bevorzugen sind. Wir erinnern uns: Mit dem Kommando  cvs diff -r1.3 -r1.4 xpenguins.c  können wir uns ansehen, welche Änderungen der andere Benutzer vorgenommen hat. Der Aufruf  cvs diff -r1.4 xpenguins.c  vergleicht die Datei in unserer Arbeitskopie mit der von dem anderen Benutzer neu eingecheckten Version. Schließlich zeigt  cvs diff xpenguins  noch mal unsere Änderungen an. (Bei dem Aufruf von diff ohne weitere Argumente wird die Datei in unserer Arbeitskopie mit der Version verglichen, die wir ausgecheckt hatten.)

Wenn sich die Änderungen vertragen, können wir unsere Datei auf den Stand der Zeit bringen:

kai@fREUNd:~/xpenguins$ cvs up xpenguins.c
RCS file: /home/kai/cvsroot/xpenguins/xpenguins.c,v
retrieving revision 1.3
retrieving revision 1.4
Merging differences between 1.3 and 1.4 into xpenguins.c
M xpenguins.c
kai@fREUNd:~/xpenguins$

CVS teilt mit, daß es die Differenz zwischen der Dateiversion, die wir ursprünglich ausgecheckt hatten, und der neuen Version ermittelt und mit dem Ergebnis die Datei gepatcht hat, die sich in unserem Arbeitsverzeichnis befunden hat. Weiterhin enthält die Datei in unserem Arbeitsverzeichnis unsere Änderungen (  M  für modified) und wir können diese nun ohne Beschwerde von CVS ins Repository übertragen:

kai@fREUNd:~/xpenguins$ cvs ci -m "Kein Konflikt" xpenguins.c
Checking in xpenguins.c;
/home/kai/cvsroot/xpenguins/xpenguins.c,v  <--  xpenguins.c
new revision: 1.5; previous revision: 1.4
done
You have new mail in /var/mail/kai
kai@fREUNd:~/xpenguins$

Spätestens jetzt sollte man sich mit dem anderen Entwickler in Verbindung setzen und sich mit ihm absprechen, bevor es zu unverträglichen Änderungen kommt. CVS bietet einen Mechanismus, der dies vereinfacht: ausgecheckte Dateien werden dann standardmäßig read-only erzeugt. Wenn man eine Datei verändern will, teilt man dies CVS mit dem Kommando  edit  mit. Die Datei wird dann schreibbar. Gleichzeitig informiert CVS andere Benutzer über diesen Vorgang, die es per  watch  dazu aufgefordert haben, die Datei für sie zu "überwachen".

1.4.4. Konfliktbewältigung

Nicht immer verläuft alles so glimpflich, wenn man sich ungenügend mit anderen Entwicklern abgesprochen hat. Angenommen wir haben eine weitere Änderung an  xpenguins.c  vorgenommen und wollen nun per  cvs up  überprüfen, ob zwischenzeitlich jemand etwas an anderen Dateien verändert hat, das wir vor unserem  checkin  noch berücksichtigen sollten. Hinter unserem Rücken hat aber jemand anderes eine Änderung an der selben Stelle von  xpenguins.c  vorgenommen und ins Repository übertragen:

kai@fREUNd:~/xpenguins$ vim xpenguins.c
kai@fREUNd:~/xpenguins$ cvs up
cvs update: Updating .
M README
RCS file: /home/kai/cvsroot/xpenguins/xpenguins.c,v
retrieving revision 1.5
retrieving revision 1.6
Merging differences between 1.5 and 1.6 into xpenguins.c
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in xpenguins.c
C xpenguins.c
cvs update: Updating penguins
kai@fREUNd:~/xpenguins$

CVS hat wieder versucht, unsere lokale Version der Datei mit den Änderungen, die inzwischen ins Repository eingetragen wurden, zu patchen, ist dabei aber auf einen Konflikt unserer Änderungen mit denen des anderen Entwicklers gestoßen. CVS hat diesen Konflikt in der Datei markiert:

            if (npenguins > MAX_PENGUINS) {
               fprintf(stderr,"Warning: only %d penguins created\n",
                     npenguins=MAX_PENGUINS);
<<<<<<< xpenguins.c
               fprintf(stderr,"Should be some more...\n");
=======
               fprintf(stderr,"And that are not enough!!\n");
>>>>>>> 1.6
            }
            else if (npenguins <= 0) {
               fprintf(stderr,"Warning: no penguins created\n");
                     npenguins=0;
                                                              87,1          16%

Solange dieser Konflikt nicht von Hand behoben wurde, d.h. solange die Markierungen nicht wieder aus der Datei entfernt wurden, nimmt CVS diese Datei bei einem  commit  nicht an.

Die Syntax der Markierungen ist möglichst einfach und gleichzeitig eindeutig gewählt. Wenn aber von zwei Entwicklern an ein und der selben Datei intensiv weiterentwickelt wurde, dann nimmt die Anzahl solcher Markierungen schnell eine Größenordnung an, bei der das Entfernen der Markierungen und der ungewollten Varianten sehr lange dauert. Konflikte sollten daher möglichst vermieden werden. Sie sind als Mittel der Absprache zwischen mehreren Entwicklern weder gedacht, noch geeignet!

1.5. Stolperfallen

In diesem Kapitel sollen einige übliche Stolperfallen bei der Benutzung von CVS angesprochen werden, die dem Anfänger (aber auch dem Fortgeschrittenen) Schwierigkeiten bereiten.

1.5.1. Umgang mit Bildern und anderen Binaries

Leider kann mit Bildern und anderen Binärdateien unter CVS nicht ganz so sorglos umgegangen werden, wie man dies gerne hätte. Dies liegt daran, daß CVS einen Mechanismus anbietet, um in ausgecheckten Dateien automatisch zu vermerken, um welche Version der Datei es sich handelt, wer sie zuletzt verändert hat und vieles mehr. Dies wird realisiert, indem der Benutzer in der Datei bestimmte Schlüsselwörter verwendet, die dann von CVS beim auschecken entsprechend verändert werden. Diese Schlüsselwörter können in einer Binärdatei natürlich an beliebig blödsinnigen Stellen zufällig vorkommen. Man muß CVS daher im Falle einer Binärdatei mitteilen, daß es keine Schlüsselwörter ersetzen soll. Dies geschieht mit dem Schalter  -kb  , ansonsten ändert sich nichts.

kai@fREUNd:~/xpenguins/penguins$ cp walker.xpm neu.xpm
kai@fREUNd:~/xpenguins/penguins$ cvs add -kb neu.xpm
cvs add: scheduling file `neu.xpm' for addition
cvs add: use 'cvs commit' to add this file permanently
kai@fREUNd:~/xpenguins/penguins$ cvs ci -m "Ein Bild" neu.xpm
RCS file: /home/kai/cvsroot/xpenguins/penguins/neu.xpm,v
done
Checking in neu.xpm;
/home/kai/cvsroot/xpenguins/penguins/neu.xpm,v  <--  neu.xpm
initial revision: 1.1
done
kai@fREUNd:~/xpenguins/penguins$

Wie man vorgeht, wenn man den Schalter  -kb  beim  c  von Bildern vergisst (was leidlich oft passiert), ist in der CVS Online-Doku beschrieben.

1.5.2. Dateien verschieben

Eine weitere Schwierigkeit, die daraus resultiert, wie CVS Dateien eines Projektes intern abbildet, besteht in der simplen Operation eine Datei zu verschieben, bzw. umzubenennen. Dies ist mit CVS schlicht nicht möglich!

Es gibt jedoch zwei Wege, dieses Problem zu umgehen, die jedoch beide Vor- und Nachteile haben:

Da eine Versions-Kontrolle, die keine korrekten Versionen liefert, wenig Sinn macht, sollte die Umbenennung im Repository nur in Ausnahmefällen durchgeführt werden!

1.5.3. Verzeichnisse verschieben

Bei Verzeichnissen bestehen die selben Schwierigkeiten, die mit den selben Workarounds umgangen werden müssen. Der Unterschied besteht darin, daß der Aufwandsunterschied zwischen den beiden Methoden wesentlich größer wird. Wenn man direkt im Repository arbeitet, kann man einfach wie gewohnt das eine Verzeichnis verschieben bzw. umbenennen. Wenn man den Repository über die Bruchstelle der Verschiebung/Umbenennung hinweg konsistent halten will, muß man alle Dateien und Verzeichnisse, die sich in dem Verzeichnis befinden, einzeln löschen und wieder einfügen! Man sollte bei CVS also bei Beginn eines Projektes genau überlegen, wie die Verzeichnisstruktur aussehen soll. Dies ist leider oft nicht möglich!

Weiterhin verwirrend in diesem Zusammenhang ist, daß sich Verzeichnisse unter CVS eigentlich gar nicht löschen lassen! Damit man trotzdem nicht alle ehemaligen Unterverzeichnisse in seiner Arbeitskopie herumfliegen hat, holt CVS Verzeichnisse bei einem  update  nicht automatisch. Man muß es mit  up -d  explizit dazu auffordern! Auf diese Weise werden gelöschte Verzeichnisse nicht bei jedem  update  neu erzeugt. Der Nachteil dabei ist, daß man schnell mal vergißt,  -d  mit anzugeben, wenn es eigentlich nötig wäre, nämlich wenn dem Repository ein neues Verzeichnis hinzugefüg wurde!

1.6. Nachtrag

Ein wesentlicher Punkt wurden in dem ursrprünglich geplanten Vortragsverlauf nicht berücksichtigt: die Erzeugung von Versionsnummerierungen, die der Sicht des Anwenders auf die einzelnen Versionen im Repository entsprechen. Dies soll hier nachgetragen werden.

1.6.1. Versionsnummern versus Tags

Die Versionsnummern, die in dem Abschnitt Weiterlaufen benutzt wurden, um die Unterschiede zwischen bestimmten, mit Hilfe des Kommandos  log  ausgesuchten Versionen anzuzeigen, stellen die interne Sicht von CVS auf die im Repository vorhandenen Versionen dar. Aufgrund der Arbeitsweise von CVS sind diese Versionsnummern nicht dafür geeignet, eine gesamte Arbeitskopie auf einen bestimmten Stand zurückzuversetzen! Dies liegt an der dateibasierten Arbeitsweise von CVS. CVS speichert die Versionen der einzelnen Dateien eines Projektes auch intern in einzelnen Dateien ab. Dies hat zur Folge, daß CVS die Versionsnummern für jede Datei eines Projektes einzeln zählt. Dateien, die besonders oft verändert und eingecheckt wurden haben daher zu einem bestimmten Zeitpunkt (z.B. bei einem Release) eine wesentlich höhere Versionsnummer als Dateien, die kaum verändert wurden, oder erst zu einem späteren Zeitpunkt erzeugt wurden. Wenn man also später seine Arbeitskopie auf den Stand dieses Releases zurückversetzen will, so kann man das nicht tun, in dem man mit  -r  die Versionsnummer angibt, die eine der Dateien zu dem Zeitpunkt des Releases hatte.

Um dieses Ziel zu erreichen, muß man dem Projekt zu diesem Zeitpunkt eine symbolische Versionsbezeichnung geben. Symbolisch, weil diese Versionsbezeichnung nicht unbedingt eine Zahlenfolge ist. Dies geschieht mit dem Kommando  tag  . Die symbolische Versionsbezeichnung muß mit einem Buchstaben anfangen und darf außer Buchstaben und Zahlen nur einen Unter- oder Bindestrich enthalten.

kai@fREUNd:~/xpenguins$ cvs tag Version-1_2kai01
cvs tag: Tagging .
T AUTHORS
T COPYING
T ChangeLog
T INSTALL
T LIESMICH
T Makefile
T README
T toon.c
T toon.h
T vroot.h
T xpenguins
T xpenguins.1
T xpenguins.c
cvs tag: Tagging penguins
T penguins/bomber.xpm
T penguins/climber.xpm
T penguins/def.h
T penguins/explosion.xpm
T penguins/faller.xpm
T penguins/floater.xpm
T penguins/neu.xpm
T penguins/tumbler.xpm
T penguins/walker.xpm
kai@fREUNd:~/xpenguins$

Dieses Kommando ordnet den Dateiversionen, die sich zur Zeit in der Arbeitskopie befinden, die symbolische Version  Version-1_2kai01  zu. Später können also genau die Dateiversionen, die sich zum Zeitpunkt des  tag  -Aufrufes in der Arbeitskopie befanden mit  cvs up -r Version-1_2kai01  wieder aus dem Repository in die Arbeitskopie geholt werden.

Zwei Bilder aus dem CVS-Buch (siehe Quellen) veranschaulichen den Nutzen von  tag 

     File A      File B      File C      File D      File E
     ------      ------      ------      ------      ------
     1.1         1.1         1.1         1.1         1.1
 ----1.2-.       1.2         1.2         1.2         1.2
     1.3 |       1.3         1.3         1.3         1.3
          \      1.4       .-1.4-.       1.4         1.4
           \     1.5      /  1.5  \      1.5         1.5
            \    1.6     /   1.6   |     1.6         1.6
             \   1.7    /          |     1.7         1.7
              \  1.8   /           |     1.8       .-1.8------->
               \ 1.9  /            |     1.9      /  1.9
                `1.10'             |     1.10    /   1.10
                 1.11              |     1.11    |
                                   |     1.12    |
                                   |     1.13    |
                                    \    1.14    |
                                     \   1.15   /
                                      \  1.16  /
                                       `-1.17-'

[Figure 2.1: How a tag might stand in relation to files's revisions.]

Die geschlängelte Linie repräsentiert dabei den Stand der Arbeitskopie zum Zeitpunkt des  tag  -Aufrufes (nicht alle Dateien befanden sich auf dem aktuellsten Stand).

     File A      File B      File C      File D      File E
     ------      ------      ------      ------      ------
                                         1.1
                                         1.2
                                         1.3
                                         1.4
                                         1.5
                                         1.6
                                         1.7
                 1.1                     1.8
                 1.2                     1.9
                 1.3                     1.10        1.1
                 1.4                     1.11        1.2
                 1.5                     1.12        1.3
                 1.6                     1.13        1.4
                 1.7         1.1         1.14        1.5
                 1.8         1.2         1.15        1.6
     1.1         1.9         1.3         1.16        1.7
 ----1.2---------1.10--------1.4---------1.17--------1.8------->
     1.3         1.11        1.5         1.17        1.9
                             1.6         1.17        1.10

[Figure 2.2: The same tag as a "straight sight" through the revision history.]

Bei der Benutzung des Kommandos  tag  sind zwei Besonderheiten zu beachten:

Es wird diesbezüglich auch keine Warnmeldung ausgegeben!

Die Tags können später ebenso wie die Versionsnummern benutzt werden.

1.6.2. Zeitreisen per Datum

Eine weitere Möglichkeit, die gesamte Arbeitskopie in einen vergangenen Zustand zurückzuversetzen, ist die Angabe eines Datums. Was bei der Angabe des Datums zu beachten ist, um wirklich die Versionen zu erhalten, die man haben möchte, ist im CVS-Buch erklärt.

1.6.3. Branching

Dort ist auch erklärt, wie man einen Tag zu dem Abzweig für einen Branch machen kann.

1.7. Weiterführende Dokumentation

* CVS Online-Doku

Online Dokumentation der CVS-Entwickler auf http://www.cvshome.org/

* The CVS Book

Online-Version eines kompletten Buches über CVS. Das Buch steht unter der GPL!

* Das CVS Buch

Die deutsche online Übersetzung dieses Buches (nicht ganz vollständig).

cvs/CvsEinführung (zuletzt geändert am 2007-12-23 22:47:30 durch localhost)