Wer an größeren Software-Projekten mitarbeitet oder mit mehreren Entwicklern zusammen an einem Projekt arbeitet, wird schnell feststellen, daß CVS die Arbeit erheblich erleichtern kann.Software-Projekte haben ab einer gewissen Größe den negativen Beigeschmack, daß die Menge an Quellcode wächst und mit der Zeit teilweise unübersichtlich wird. Dateien wurden bereits in verschiedene Verzeichnisse, nach Kategorien sortiert, aufgeteilt und mit »make« zu einem Projekt zusammengefaßt. Beschäftigt man sich jedoch nicht ständig damit, vergißt man leicht, wie Dinge organisiert wurden.
Erschwert wird es, wenn mehrere Leute an den gleichen Dateien arbeiten und nicht sogenannte »Patches« oder »Diffs« schicken, sondern nur die geänderten Dateien. Der Verwalter muß die Änderungen dann finden und manuell übernehmen. Patches sind Dateien, die Unterschiede zur bisherigen Version enthalten. Sie werden automatisch mit dem Programm »patch« übernommen und mit »diff« erzeugt, daher die Namen.
Prinzipiell läßt sich Quellcode mit Patches sinnvoll mit mehreren Leuten bearbeiten, doch hat der Verwalter des gesamten Codewerkes die Aufgabe, diese »Patches« einzuarbeiten. Solange es keine Überschneidungen gibt, bereitet das keine Probleme. Überschneiden sich jedoch die Ergänzungen verschiedener Leute oder haben sie mit unterschiedlichen Versionen des Quellcodes gearbeitet, muß der Verwalter die Arbeiten unter Umständen manuell an den aktuellen Code anpassen. Je nach Umfang kann das zeitaufwendig werden.
Bedingt durch den Umfang eines Projekts passiert es hin und wieder, daß bestimmte Funktionen in einigen Versionen plötzlich nicht mehr wie gewünscht arbeiten. Verursacht wird das durch unbeabsichtigte Seiteneffekte von Routinen. Hilfreich wäre es, wenn man sich die Unterschiede zwischen verschiedenen Versionen anzeigen lassen könnte sowie die Idee, weshalb etwas geändert wurde.
RCS kontrolliert verschiedene Versionen von einer einzelnen Datei. Daher ist es nur für eigenständige Dateien (z.B. Konfigurationsdateien in »/etc«) geeignet. CVS hingegen arbeitet mit Verzeichnissen und Modulen. Es läßt sich dadurch gut für komplette Projekte einsetzen.
Der Sinn von CVS besteht darin, volle Kontrolle über den Quellcode zu erhalten und die Arbeit, insbesondere mit mehreren Leuten, zu erleichtern. Dabei wird folgendes geboten:
Wurde jedoch an den gleichen Dateien von anderer Seite gearbeitet, so versucht CVS die Änderungen entsprechend einzuarbeiten. Wenn innerhalb der Dateien an unterschiedlichen Stellen gearbeitet wurde, klappt das meistens. Schlägt es jedoch fehl, muß der Entwickler die Änderungen manuell in die neue Version einarbeiten und das Resultat erneut ins Archiv aufnehmen.
Wenn die eigenen Änderungen ins Archiv übernommen werden, fügt CVS automatisch einen Zeitstempel (wann wurden die Änderungen übernommen), den Benutzernamen (wer spielt die Änderungen ein) und einen Kommentar (was wurde geändert) hinzu. Der Kommentar wird nicht automatisch vergeben. Er sollte die Änderungen beschreiben, damit sie später leichter nachvollzogen werden können. Man kann CVS darüberhinaus auch so einrichten, daß die Kommentare mit oder ohne Änderungen via Mail verschickt werden, so daß alle Teilnehmer immer auf dem laufenden sind.
Da CVS im Gegensatz zu RCS nicht nur für einzelne Dateien konzipiert wurde, sondern für komplexe Projekte, werden oft zusätzlich zu den Revisionen symbolische Namen (sogenannte Tags, engl. für Anhänger, gesprochen "tägg") vergeben. Tags sind Datei- und Verzeichnis-übergreifend und werden jeweils für alle Dateien im Archiv vergeben. Sie werden von den Mitarbeitern des Projekts vergeben. Solche Markierungen werden normalerweise dann verwendet, wenn eine neue Version des gesamten Projekts freigegeben wird. Dadurch läßt sich später exakt nachvollziehen, wie alte Versionen des Projekts ausgesehen haben und was sich zwischen verschiedenen Versionen geändert hat.
Damit »cvs« weiß, mit welchem Archiv es arbeiten soll und welches Modul es lokal bereitstellen soll, müssen beide angegeben werden. Das Archiv wird mit der Umgebungsvariablen »CVSROOT« gesetzt (z.B. mit »export CVSROOT=/archive«), oder in der Kommandozeile mit dem »cvs«-Parameter »-d /archive« angegeben. Dem »checkout«-Befehl muß zusätzlich das Modul mitgeteilt werden, das "ausgecheckt" werden soll. Damit sieht eine Befehlszeile z.B. wie folgt aus:
cvs -d /archive checkout xtermsetDieser Befehl erzeugt ein Verzeichnis »xtermset« und legt die neuesten Revisionen aller Dateien des Moduls »xtermset« dort an. Falls nötig, werden auch Unterverzeichnisse angelegt.
Soll eine alte Version ausgecheckt werden, so muß zusätzlich der Tag angegeben werden, auf den sich die Dateien beziehen sollen. Dazu wird dem »checkout«-Befehl ein Parameter übergeben, er muß daher nach dem Wort »checkout« angegeben werden. Mit »-r tag« wird der zu benutzende Tag angegeben, wenn nicht die neuesten Revisionen der Dateien verwendet werden sollen. Man würde folgenden Befehl benutzen:
cvs -d /archive checkout -r xtermset_0_1 xtermsetIn jedem Verzeichnis, das von CVS kontrolliert wird, wird ein Unterverzeichnis mit dem Namen »CVS« angelegt. In diesem werden verschiedene Statusdateien abgelegt, damit wichtige Informationen bei weiteren Operationen bekannt sind. Es darf nicht gelöscht werden.
Man könnte stattdessen auch ein neues Verzeichins mit den neuesten Dateien anlegen. Das ist jedoch bei großen Projekten, die mehrere Megabytes groß sind, nicht sinnvoll. Insbesondere, wenn auf dessen Server über das Internet zugegriffen wird, dauert es unter Umständen ziemlich lange, bis die Dateien neu auf die eigene Festplatte kopiert wurden.
Es ist daher sinnvoller, die lokale Kopie als Grundlage zu nehmen und nur die Dateien auf den neuesten Stand zu bringen, die geändert wurden. Dieses erledigt der Befehl »cvs update«. Dabei muß das Repository nicht mehr angegeben werden, da es in den internen Dateien gespeichert wurde.
Auf diese Weise arbeiten viele Hunderte Entwickler an großen internationalen Projekten wie Gnome oder Mozilla mit. Alle paar Tage übertragen sie ihre eigenen Änderungen an das offizielle Archiv und aktualisieren ihre lokalen Verzeichnisse. Bedingt durch die Zeitverschiebung, ist praktisch immer Bewegung im Archiv.
Bevor die eigenen Änderungen ins zentrale Archiv aufgenommen werden, sollten sie auf jeden Fall kontrolliert werden. Wenn man nicht aufpaßt, ändert man sonst leicht unbeabsichtigt an falschen Stellen etwas oder bringt den Code durcheinander. Wird ein Programm verbessert oder erweitert, dann sollte nur dort etwas geändert werden, wo es nötig ist, sonst werden Änderungen schwer nachvollziehbar.
Wenn bekannte Fehler gesucht und behoben werden, muß der Entwickler besonders sorgfältig vorgehen. Je nach Komplexität des Problems kann es nötig werden, den Code an vielen Stellen zu untersuchen, temporär zu verändern und zusätzliche Routinen hinzuzufügen. Ist der Fehler schließlich beseitigt, muß der Quellcode wieder "geglättet" werden. Die temporären Änderungen dürfen nicht versehentlich ins reguläre Archiv übernommen werden.
Wie findet man die Änderungen am einfachsten - ohne erneut alle Dateien durchzusuchen? Hier unterstützt CVS den Entwickler ebenfalls. Mit einem Befehl lassen sich alle Änderungen an den Dateien anzeigen. Verglichen wird mit der gleichen Revision im CVS-Archiv:
cvs diffOhne Parameter vergleicht dieser Befehl jede Datei im aktuellen Verzeichnis und in dessen Unterverzeichnissen mit dem Repository. Man muß sich daher in einem Verzeichnis innerhalb der lokalen Arbeitskopie befinden, wenn man den Befehl aufruft. Dateien, die nicht im CVS-Archiv vorhanden sind, werden gesondert behandelt. Sie werden auf der Standardfehlerausgabe (»stderr«) mit einem vorangestellten Fragezeichen angezeigt. Der Entwickler entscheidet dann, ob es ein Fehler ist, oder ob diese Dateien ignoriert werden dürfen.
CVS verwendet jeweils die gleichen Revisionen der Dateien, die früher ausgecheckt oder aktualisiert wurden. Dieser Befehlt macht daher ausschließlich Änderungen an den lokalen Dateien sichtbar. Er unterstützt darüberhinaus die Angabe von Datei- und Verzeichnisnamen als Parameter. In dem Fall vergleicht CVS nur die angegebenen Dateien bzw. Verzeichnisse. Dieser Befehl sollte immer dann benutzt werden, wenn die eigenen Änderungen ins Archiv aufgenommen werden sollen.
Die Flexibilität wird bei Verwendung der zusätzlichen Parameter »-r« und »-D« sichtbar. Mit »-r« wird, wie oben erwähnt, ein Tag angegeben, auf dessen Basis die Unterschiede ermittelt werden. Mit dem Parameter »-D« wird hingegen ein Referenzdatum festgelegt. Die nebenstehende Tabelle führt verschiedene Datumsformate an, die von CVS unterstützt werden. Wenn die Datumsangabe Leerzeichen enthält, muß sie in einfache oder doppelte Hochkommas gesetzt werden.
| Datumsformate für »cvs« |
|---|
| 1 month ago |
| 2 hours ago |
| 400000 seconds ago |
| last year |
| last Monday |
| yesterday |
| a fortnight ago |
| 3/31/92 10:00:07 PST |
| January 23, 1987 10:05pm |
| 22:00 GMT |
Wird einer dieser Parameter angegeben, so bezieht der »diff«-Befehl nicht mehr auf die gleichen Revision im CVS-Archiv, sondern auf die Revisionen, die dem angegebenen Tag oder Datum entsprechen. So lassen sich z.B. die Änderungen der letzen Monate, relativ zur lokalen Kopie herausfinden.
Die Parameter »-D« und »-r« dürfen zweimal angegeben werden. In dem Fall berechnet CVS die Unterschiede der lokalen Dateien zwischen den angegebenen Tags oder Daten. Lokale Änderungen werden teilweise nicht mehr beachtet. Es dürfen maximal zwei dieser Parameter angegeben werden, wobei »-r« und »-D« gemischt werden dürfen.
CVS Unterstützt zwei implizite Tags, die immer vorhanden sind und automatisch verwendet werden, wenn weder Tags noch Daten angegeben werden. Mit »HEAD« wird die jeweils neueste Revision im Repository bezeichnet, mit »BASE« wird die Revision bezeichnet, die im lokalen Arbeitsverzeichnis verwendet wird.
Möchte man sehen, was Kollegen bisher bearbeitet haben, z.B. bevor man das lokale Arbeitsverzeichnis aktualisiert, dann werden diese Tags verwendet. Gesucht sind die Unterschiede zwischen dem lokalen Arbeitsverzeichnis (also »BASE«) und den neuesten Revisionen im Archiv (also »HEAD«). Das eledigt folgender Befehl:
cvs diff -r BASE -r HEADZur Verdeutlichung der Auswirkungen wird die Ausgabe dieses Befehls bei einem normalen CVS-Archiv, auf dem mehrere Personen arbeiten, mit der Ausgabe des folgenden verglichen.
cvs diff -r HEAD -r BASEEs ist leicht zu erkennen, daß die Änderungen bei diesem Befehl in umgekehrter Richtung angezeigt werden.
Wie Sie sicherlich bereits vermutet haben, stützt sich »cvs diff« auf das unter Unix übliche Kommando »diff« ab. Mit diesem Befehl werden Unterschiede in zwei Textdateien angezeigt. Das dabei verwendete Format wurde standardisiert und läßt sich maschinell weiterverarbeiten. Mit diesem Programm erzeugen Entwickler sogenannte Patches, die sie den Autoren schicken oder den Anwendern zur Verfügung stellen.
Wenn nicht anders angegeben, erscheint die Ausgabe von »diff« im einfachsten Format, in dem nur die veränderten Textstellen angezeigt werden. Das Format ist sehr technisch und nicht so leicht für Menschen zu lesen. Daher verwendet man oft das sogenannte »context«-Format (»-c«) oder das »unified«-Format (»-u«). Bei beiden werden zusätzlich ein paar Zeilen vor und nach der Veränderung angezeigt und nicht nur die geänderte Zeile selbst.
Um das Ausgabeformat von »cvs diff« zu ändern, wird eine Zeile zur lokalen Konfigurationsdatei ».cvsrc« im Home-Verzeichnis des Benutzers hinzugefügt: Das Schlüsselwort »diff« gefolgt vom gewünschten Parameter. In der Datei steht also
diff -coder
diff -uDerartig generierte Patches werden mit dem Programm »patch« verarbeitet. Es liest sie Stück für Stück und führt die Änderungen an den angegebenen Dateien durch. Wenn sich in den zu verändernden Dateien die Zeilennummern geändert haben, die angegebenen Code-Passagen jedoch noch vorhanden sind, werden weiterhin die passenden Stellen modifiziert. Durch diese Technik wird verhindert, daß immer der gesamte Quellcode übertragen werden muß. Es wird ermöglicht, daß lokale Änderungen auch weiterhin automatisch in neuere Versionen von Programmen eingebaut werden können.
Da CVS neben den Änderungen auch immer einen Kommentar speichert, werden Sie nach Eingabe dieses Befehls gebeten, einen Text einzugeben. Dazu wird ein Editor geöffnet, in dem Sie beliebig viele Zeilen schreiben dürfen. Alternativ geben Sie mit »-m 'text'« einen Kommentar direkt in der Befehlszeile an. Dieser Text wird später über den Log-Befehl abgerufen und wird bei größeren Archiven sogar per Mail an die Teilnehmer verschickt. Sie sollten an dieser Stelle die Änderungen beschreiben, damit sie leichter nachvollzogen werden können.
In der Voreinstellung wird als Editor ein »vi« aufgerufen. Das ist der Standard-Editor unter Unix, zu dem wir später eine Kurzreferenz geben werden. Bevor Sie den Kommentar eingeben, müssen Sie »i« drücken, um in den Eingabemodus zu gelangen. Schreiben Sie den Text im oberen Teil der Datei, oberhalb der waagerechten Linie. (siehe nebenstehende Abbildung)
CVS hat bereits Erklärungen in die Datei eingefügt, bevor sie an den Editor übergeben wurde. Darin wird unter anderem beschrieben, welche Dateien betroffen sind und für welche Dateien Ihr Kommentar ins Archiv geschrieben wird. CVS unterscheidet dabei Dateien, die verändert wurden, die neu hinzugekommen sind oder gelöscht wurden. An diesen Zeilen sollten Sie nichts ändern. Sie werden von CVS später wieder gelöscht und nicht ins Archiv übernommen.
Wenn Sie den Text fertig geschrieben haben, drücken Sie »ESC«, um in den Befehlsmodus zurückzukehren. Dort geben Sie »:wq« ein, speichern den Text und verlassen den Editor. Den eingestellten Editor können Sie beliebig ändern. Gesteuert wird er durch die Umgebungsvariable »EDITOR«. Mit dem Befehl »export EDITOR=joe« stellen Sie z.B. den Editor »joe« als Standardeditor ein.
Das hat jedoch mehrere Nachteile. Zum einen würde der Name des Verzeichnises nicht die aktuelle Version beinhalten. Dazu muß man wissen, daß Verzeichnisse in derartigen Paketen zur Unterscheidung meistens »foo-x.y« heißen, wobei »foo« der Name des Projekts ist und »x.y« die aktuelle Versionsnummer. Zum anderen würden unter Umständen überflüssige Dateien ins Archiv aufgenommen werden, wenn vergessen wurde, sie zu löschen. Zu guter Letzt würde das Archiv alle Unterverzeichnisse »CVS« enthalten, die jedoch nur für die interne Arbeit von »cvs« benötigt werden.
All das will man nicht in freigegebenen Versionen haben, die tausendfach im Internet zur Verfügung gestellt werden. Hinzukommt, daß man die freigebenen Dateien mit einer zusätzlichen Markierung versehen sollte, bevor man sie freigibt. Nur dadurch kann gewährleistet werden, daß man später die gleiche Version erneut aus dem Archive herausziehen und mit anderen Versionen vergleichen kann.
Wie bereits angesprochen, kann man mit CVS zusätzlich zu den normalen Revisionen der Dateien symbolische Namen, sogenannte Tags, vergeben. Sie werden üblicherweise dazu verwendet, um Zustände zu fixieren. Die Zustände können später problemlos mit einem einzigen Befehl aus dem Archiv wiederhergestellt werden.
Tags sind prädestiniert dafür, alle beteiligten Dateien für eine freizugebende Version oder eine Vorabversion zu markieren. Die Markierung sollte die Versionsnummer oder bei Vorabversionen das Datum wiederspiegeln. Der symbolische Name darf aus Buchstaben, Ziffern, dem Binde- und Unterstrichen bestehen. Das erste Zeichen darf zur Unterscheidung von Revisionen keine Ziffer sein.
Heißt das Projekt zum Beispiel »xtermset« und soll die Version 0.2.3 freigegeben werden, dann würde man als Tags »xtermset_0-2-3« oder »joey_xtermset_0-2-3« verwenden. Wenn mehrere Leute am Projekt mitarbeiten und Versionen freigeben, ist es teilweise sinnvoll, deren Login mit in den symbolischen Namen aufzunehmen, wie es nebenstehender Abbildung auch zu sehen ist. Der vollständige Befehl sieht dann wie folgt aus:
cvs tag joey_xtermset_0-2-3Anschließend wird die so markierte Version "exportiert". Dabei verlieren die Verzeichnisse die von CVS benötigten Informationen. Die Verzeichnisse »CVS« werden nicht angelegt. Es werden zudem nur die Dateien exportiert, die im Archiv vorhanden sind und mit der entsprechenden Markierung versehen sind. Gelöschte Dateien werden nicht exportiert.
Damit die exportierten Dateien in ein einheitliches Verzeichnis geschrieben werden, das die Versionsnummer enthält, muß dieses mit dem Parameter »-d« angegeben werden. Damit CVS weiß, welche Version verwendet werden soll, muß der vorher definierte symbolische Name ebenfalls angegeben werden. Das geschieht wie bisher über den Parameter »-r«. Anschließend wird das Verzeichnis mit »tar« zusammengefaßt und mit »gzip« komprimiert. Die Befehle sehen wie folgt aus:
cvs export -r joey_xtermset_0-2-3 -d xtermset-0.2.3 xtermset tar cvf xtermset-0.2.3.tar xtermset-0.2.3 gzip -9 xtermset-0.2.3.tarDas Verzeichnis »xtermset-0.2.3« wird nicht mehr benötigt und darf gelöscht werden. Wenn das CVS-Archiv lokal vorliegt, wird das Arbeitsverzeichnis »xtermset« ebenfalls nicht mehr benötigt. Wird auf den CVS-Server jedoch über das Internet zugegriffen, dann sollte das Verzeichnis aus Zeit- und Kostengründen bestehen bleiben und für die weitere Entwicklungen benutzt werden.
Werden weitere Dateien bearbeitet, die auch in die Obhut von CVS aufgenommen werden sollen, dann müssen sie zuerst in die lokale Kontrolle von CVS aufgenommen werden. Das geschieht mit dem Befehl »cvs add«. Als Parameter werden die Dateien oder Verzeichnisse angegeben, die hinzugefügt werden sollen. Die Dateien werden damit jedoch noch nicht ins Archiv aufgenommen, sondern lediglich für das nächste »commit« markiert. Gleiches gilt für Verzeichnisse.
Sollen Dateien aus dem Archiv gelöscht werden, dann müssen sie zuerst im Verzeichnis gelöscht werden und anschließend zum Löschen markiert werden. Der Befehl »cvs rm« erledigt das. Wie beim Hinzufügen, werden die Dateien als Argumente angegeben, die gelöscht werden sollen. Aktiv werden die Änderungen erst dann, wenn sie mit »cvs commit« im Archiv durchgeführt werden.
Möchte man wissen, ob von einer Datei eine neuere Revision auf dem Server liegt oder ob die Datei überhaupt im Repository vorhanden ist, wird der »status« Befehl verwendet. Mit »cvs status -v« erhält man überdies eine detailierte Auflistung samt aller vergebenen Tags. Mit dem normalen Befehl »cvs status« ist die Liste kürzer, wie nebenstehende Abbildungen verdeutlichen.
In diesen Dateien wird pro Modul festgelegt, ob und wie Änderungen per Mail verschickt werden. Wenn über das Netzwerk auf's Archiv zugegriffen wird, liegt dort eine zusätzliche Paßwort-Datei. Werden Module in Verzeichnisse aufgeteilt, so besteht die Möglichkeit in der Datei »modules« Aliases zu vergeben. Kurzum: Es müssen eine Reihe von Dateien angelegt werden, damit ein Repository funktionsfähig ist. Die folgenden Befehle erledigen dieses:
mkdir /archive cvs -d /archive init
Wird der Parameter »-d« weggelassen, dann muß die Variable »CVSROOT« verwendet werden. Bestehende Projekte werden anschließend mit dem »import«-Befehl ins Archiv aufgenommen. Die Syntax lautet wie folgt:
cvs import [-options] repository vendortag releasetagAls »repository« wird der Name des Moduls angegeben, der »vendortag« bezeichnet die Quelle der Dateien und der »releasetag« vergibt für diese Version gleich einen symbolischen Namen. Für diesen Befehl muß man sich bereits im Verzeichnis befinden, das ins Archiv aufgenommen werden soll. Ein derartiger Befehl sieht dann wie folgt aus:
cvs import -ko -m 'Import of bare source' xtermset \
source-dist upstream_xtermset_0-3
Anschließend wird das Verzeichnis gelöscht und vom gerade
eingespielten Modul mit »cvs checkout« eine lokale Arbeitskopie
angelegt.
Die zweite Methode geht über den »pserver«, der eine direkte Netzwerkverbindung akzeptiert. Die Verbindung wird über den Internet-Server »inetd« angenommen und an CVS weitergeleitet. Für diese Methode wird eine eigene Paßwort-Datei benötigt. Da kein Account auf dem Server vorhanden sein muß, eignet sich dieses Protokoll für anonymes CVS, über das die Teilnehmer lesend auf die Module zugreifen können.
Diese Technik wird zum Beispiel bei Gnome eingesetzt. Um derart auf ein CVS-Archiv zugreifen zu können, wird das Repository wie folgt angegeben:
CVSROOT=:pserver:anonymous@anoncvs.gnome.org:/cvs/gnome export CVSROOTAls nächstes logt man sich mit »cvs login« ein und gibt ein leeres Paßwort an. Anschließend wird wie bisher gearbeitet. Wenn man auch Schreibzugriff auf ein solches Archiv hat, muß der Benutzername »anonymous« durch den eigenen ersetzt werden.
| Tabelle: CVS-Befehle | |
|---|---|
| checkout | Anlegen der lokalen Kopie (abgekürzt »co«) |
| update | Lokale Kopie mit Repository abgleichen |
| commit | Repository mit lokaler Kopie angleichen (abgekürzt »ci«) |
| log | Kommentare anzeigen |
| status | Status anzeigen (abgekürzt »stat«) |
| diff | Unterschiede anzeigen |
| add | Datei oder Verzeichnis hinzufügen (mit »commit« aufnehmen) |
| rm | Datei oder Verzeichnis löschen (mit »commit« übernehmen) |
Martin Schulze