Aus Linux-Magazin 06/2003

Subversion auf den Spuren von CVS

Obwohl CVS als Versionskontrollsystem nicht das Gelbe vom Ei ist, hat es einen großen Vorteil gegenüber besseren, aber kommerziellen Alternativen: Es ist freie Software. Mit Subversion bekommt es Konkurrenz.

Irgendwann in ihrer Laufbahn kommen die meisten Entwickler mit CVS[2] als dem De-facto-Standard bei Sourcecode-Managern (SCM) für freie Softwareprojekte in Berührung. Als solcher verfügt CVS über eine riesige User-Basis und hat sich einen guten Ruf erworben. Doch leidet es an diversen Designfehlern, so mancher Projektmanager ist schon an fehlender oder umständlich zu handhabender Funktionalität verzweifelt.

Von diesen Unzulänglichkeiten angespornt, setzte es sich das Subversion-Projekt[1] zum Ziel, einen überzeugenden Nachfolger für CVS innerhalb der Open-Source-Gemeinde zu kreieren. Das heißt nichts anderes, als dass dieser SCM die gesamte Funktionalität von CVS mit dem bekannten Interface anbieten, gleichzeitig aber dessen Fehler vermeiden und besser sein will.

Untypisch für ein Open-Source-Projekt arbeiten einige Entwickler von Anfang an in Vollzeit an Subversion. Die Firma Collab Net zahlt deren Gehälter; sie hält auch die Rechte am Code, den sie unter einer Lizenz ähnlich der von BSD oder Apache herausgibt.

Noch nicht fertig, aber einsatzfähig

Derzeit liegt Subversion noch im Alphastatus vor. Mit anderen Worten: Die Software gilt als Release-fähig, befindet sich aber noch in der aktiven Entwicklungsphase. An den Features arbeiten und feilen die Entwickler weiter, Bugs werden laufend entdeckt und ausgemerzt. Für alle, die Bedenken haben, ihre Projekte mit einer Alpha-Software zu verwalten, sei jedoch angemerkt, dass das Subversion-Team seinem eigenen Produkt vertraut: Seit anderthalb Jahren verwaltet sich das Projekt selbst, und zwar ohne Datenverlust.

Wer CVS seit Jahren zur vollkommenen Zufriedenheit einsetzt, mag sich fragen, was mit den oben erwähnten Designfehlern gemeint ist. CVS leidet unter einigen Problemen, die sich in erster Linie aus seiner Abhängigkeit vom RCS-Dateiformat für die Versionsverfolgung ergeben. Im Folgenden geht der Artikel auf jene Schwierigkeiten ein, für die Subversion eine Lösung bietet.

Atomare Commits

Wenn ein Benutzer Änderungen am Quellcode ins Sourcecode-Repository einpflegt (Commit), sollten Versionskontrollsysteme (in diesem Punkt vergleichbar mit Datenbanken) dafür sorgen, dass alle Änderungen entweder akzeptiert oder abgelehnt werden. Man spricht hier von atomarem Verhalten. CVS gewährleistet dies nicht; das System verhält sich nur auf Dateiebene atomar.

Mit anderen Worten: Wenn Sie Änderungen an zehn Dateien comitten wollen, jemand anderes quasi gleichzeitig eine Korrektur veranlasst und damit die achte Datei auf Ihrer Liste modifiziert, akzeptiert CVS Ihre Änderungen an den ersten sieben Dateien und lehnt den Rest ab. In diesem Fall bleibt der Zustand des Repository so lange inkonsistent, bis Sie den Konflikt aufgelöst und Ihre restlichen Änderungen eingestellt haben.

Weil CVS keine Möglichkeit bietet, Änderungen an mehreren Dateien zu gruppieren, können Sie nicht mal Ihre eigenen, teilweise erfolgten Commits rückgängig machen, ohne dabei auch die Änderung zurückzuziehen, die der andere Entwickler veranlasst hatte.

Ein Beispiel zur Verdeutlichung des Problems: Tom und Dirk arbeiten zeitgleich an einem Sourcecode-Baum, der drei Dateien enthält: »a.c«, »b.c« und »c.c«. Zufällig versuchen die beiden gleichzeitig Änderungen einzustellen. Kurz vor dem Commit überzeugen sie sich jeweils davon, dass ihre Daten mit der Datenbasis im Repository synchron sind.

Während Tom seine Änderungen an »a.c« für das CVS-Log dokumentiert, comitted Dirk eine Korrektur an »b.c«. Bevor Dirk fertig ist, checkt Tom seine veränderte Datei »c.c« ein. Beim Einstellen seiner Änderungen stellt Dirks Maschine fest, dass Tom »c.c« gesperrt hat, und informiert ihn, dass seine Version von »c.c« nicht mehr aktuell ist. Dirk synchronisiert seine Daten, um Toms Änderungen zu übernehmen, und stellt fest, dass ein Konflikt mit »c.c« entstanden ist, den er jetzt (vielleicht zusammen mit Tom) beheben muss.

In der Zwischenzeit bringt Harry seinen Quelltext auf den neuesten Stand und bekommt Toms Änderungen an »a.c« und »c.c« sowie Dirks Änderung an » b.c« zu sehen, Dirks Änderung an »c.c« bleibt ihm jedoch vorenthalten. Er versucht, das Projekt zu kompilieren, und stellt fest, dass es nicht geht. Der langen Rede kurzer Sinn: Bis Tom und Dirk den Konflikt von Dirk aufgelöst haben, sind weder Tom, noch Dirk, noch Harry im Besitz einer funktionierenden Kopie des Quellcodes.

Subversion implementiert atomare Commits. Wenn Sie eine Änderung an einem Subversion-Repository veranlassen, lösen Sie dort eine Transaktion aus. Sollte ein Teil des Commits fehlschlagen, setzt der SCM die Transaktion wieder zurück und lehnt den gesamten Commit ab.

Umbenennungen

CVS bietet keine Möglichkeit, Dateien umzubenennen und gleichzeitig die Versionshistory beizubehalten. Wenn »file1« mit der Aktion

mv file1 file2
cvs remove file1
cvs add file2
cvs commit

in »file2« umgetauft wird, legt der SCM die neue Datei »file2« an, ohne jedoch die History der alten Datei »file1«, die inzwischen im Attic gespeichert ist, zu übernehmen. Bei Subversion reichen die Kommandos

svn move file1 file2
svn commit

für diese Aufgabe aus, die gemeinsame History von »file1« und »file2« geht dabei nicht verloren.

Abgesehen davon erweitert Subversion die Versionsüberwachung dramatisch. Verzeichnisse und Metadaten von Dateien, umbenannte oder kopierte Dateien – alle unterliegen der Versionierung. Subversion-Nutzer können also nicht nur Dateien, sondern auch Verzeichnisse verschieben und kopieren.

Kopien legt der SCM Platz sparend und auf bestechend einfache Weise an: Die erste Kopie ähnelt einem Hardlink auf eine bestimmte Version des Verzeichnisses. Wenn Sie Dateien in einem Branch anpassen, werden nur die geänderten Dateien in diesen Zweig des Repository kopiert. Sowohl die Erstellung als auch die Pflege von Branches geht bei Subversion Zeit und Speicherplatz sparend vonstatten.

Branches und Tags

Wenn ein CVS-Repository mit einem Tag versehen wird, markiert der SCM jede Datei im Verzeichnisbaum entsprechend. Auch beim Branching bekommen alle betroffenen Dateien das so genannte Branch-Tag verpasst. Damit steigt der Aufwand fürs Branching und Tagging in großen Repositories und Verzeichnisbäumen proportional zur Anzahl der zu verarbeitenden Dateien.

Subversion implementiert beide Operationen so, dass der Zeitaufwand konstant bleibt. Tatsächlich unterscheidet Subversion gar nicht zwischen Tags und Branches. Beide sorgen intern dafür, dass das zu kennzeichnende Verzeichnis einfach nur kopiert wird, und verursachen somit genauso viel Aufwand wie jede andere Kopieroperation.

Schließlich gibt es von der Logik her keinen Unterschied zwischen Branching und Tagging. Ein Tag ist nichts anderes als die Kopie einer Gruppe von Dateien zu einem bestimmten Zeitpunkt, während ein Branch eine Kopie einer Gruppe von Dateien zu einem bestimmten Zeitpunkt ist, die unabhängig vom Rest des Baums verändert werden darf. Folglich handelt es sich bei einem Tag um einen unveränderlichen Branch. Unter Subversion ist das tatsächlich der Fall. Wenn Sie eine Datei in einem mit Tags versehenen Baum ändern und diese Änderung comitten, wird das Tag plötzlich zu einem Branch.

Abbildung 1: Dank Apache als Backend haben Webbrowser Zugriff auf Subversion-Repositories.

Abbildung 1: Dank Apache als Backend haben Webbrowser Zugriff auf Subversion-Repositories.

Zeitökonomie

Fordert man eine Datei aus einem CVS-Zweig an, verhält sich der Zeitaufwand proportional zur Anzahl der Revisionen zwischen dem Anfang des Branch-Punktes und dem HEAD-Branch zuzüglich der Anzahl der Revisionen für den HEAD seit dem Branch-Punkt. RCS- Dateien speichern die neueste Revision als Volltext im HEAD, sie muss also jedes Mal wieder hergestellt werden, wenn man den Text einer anderen Version anfordert.

Für eine Datei in einem Branch bedeutet dies, dass alle Änderungen vom HEAD bis zum Branch-Punkt rückgängig gemacht und alle Änderungen für diesen Zweig angewandt werden müssen, um aus Sicht des Entwicklers die vollständige Datei zu ergeben. Aus diesem Grund verhält sich die Anzahl der Diffs, Branch-Switches und Checkouts etwa proportional zur Anzahl der Revisionen in einer CVS-Datei, wenn diese Operationen in einem Branch stattfinden. Subversion bewältigt alle Branch- und Tag-Operationen in einer konstanten Zeit.

Binäre Diffs

Die Speicherung von binären Dateien in CVS ist ein ziemlicher Alptraum. Weil das RCS-Dateiformat textbasiert ist, führen Änderungen an einer Binärdatei dazu, dass das alte File komplett ersetzt wird. So belegen die Versionen einer 100 KByte großen Bilddatei wie etwa der Gimp-Splashscreen nach kurzer Zeit mehrere MByte an Speicherplatz im Repository, wenn sie bei jeder Release ausgewechselt werden.

Subversion nutzt einen Algorithmus namens Vdelta zum Erfassen der Unterschiede zweier Dateiversionen. Er ermöglicht nicht nur ein sehr effizientes Diffing reiner Text-, sondern auch von Binärdaten. Damit sind die Probleme bei der Versionierung von Postscript- oder PDF-Dokumenten Geschichte.

Client-Server-Kommunikation

Wenn Sie unter CVS eine Datei lokal ändern und danach wissen wollen, wie sich Ihre Kopie von der gespeicherten Version unterscheidet, sendet der Client das gesamte File an den Server. Der ermittelt die Unterschiede und gibt das Ergebnis an den Client zurück. Ähnliches gilt für alle Operationen, die auf lokal modifizierte Dateien zurückgreifen, etwa Updates, Commits und Merges (Verschmelzungen): Der Aufwand wächst proportional mit der Größe der geänderten Dateien auf dem Client, nicht mit der Größe der Änderung.

Subversion nutzt einen anderen Ansatz: Seine Entwickler gehen davon aus, dass Speicherkapazität eher zur Verfügung steht als Bandbreite und dass man daher die Nutzung der Bandbreite auch dann minimieren sollte, wenn die Ausweitung der Speicherkapazität Kosten verursacht. Wenn Sie ein Subversion-Repository aktualisieren, legt der SCM eine Kopie der neuesten Revision desselben lokal an und pflegt die Änderungen gleichzeitig in die lokale Kopie ein.

Aus diesem Grund werden Diffs unter Subversion in beide Richtungen übertragen. Wollen Sie eine lokale Datei ändern und einchecken, überträgt der Client lediglich die Unterschiede zwischen der lokalen Datei und der neuesten lokal gespeicherten Revision an den Server, eine Arbeitsweise, die viel weniger Bandbreite beansprucht.

Da lokal eine saubere Kopie des Repository vorliegt, bleiben serverbasierte und lokale Operationen getrennt voneinander. Damit können Sie beispielsweise feststellen, welche lokalen Dateien modifiziert wurden und welche Änderungen Sie an diesen Dateien vorgenommen haben, ohne auf den Server zuzugreifen.

Tatsächlich verhält sich der Aufwand für Subversion-Operationen im Allgemeinen proportional zur Größe der Änderung, nicht zur Größe des Repository oder der zu ändernden Dateien.

Repository-Versionen

Subversion versioniert nicht einzelne Dateien wie CVS, sondern das Repository als Ganzes. Wenn Sie etwas einchecken, initiiert der SCM eine Transaktion; Ihre Änderungen landen im Repository. Wenn dabei keine Probleme auftreten, bekommt das neue Repository mit Ihren Änderungen anschließend eine neue Versionsnummer.

Diese Methode bietet verschiedene Vorteile gegenüber CVS. Der wichtigste besteht darin, dass atomare Schreiboperationen möglich sind. Außerdem lassen sich so Änderungen, die gleichzeitig durchgeführt wurden (so genannte Changesets), problemlos abrufen – dabei handelt es sich schließlich um nichts anderes als um die Differenz zwischen zwei aufeinander folgenden Repository-Versionen.

Tabelle
1: Gängige Subversion-Befehle

 

Befehl

Beschreibung

co/checkout

Erzeugt eine lokale Arbeitskopie des Quellcodes.

ci/commit

Schreibt lokale Änderungen ins Repository.

up/update

Aktualisiert die Arbeitskopie so, dass sie anschließend
alle Änderungen am Repository seit dem letzten Update
enthält.

status

Fasst lokale Änderungen zusammen, ohne sich mit dem
Repository auszutauschen, oder zeigt veraltete Ressourcen auf, ohne
die Arbeitskopie zu aktualisieren (kein Äquivalent in
CVS).

add, rm/remove

Fügt bisher nicht im Repository enthaltene Dateien ein
oder entfernt Files aus dem Projekt.

cp/copy, mv/move

Kopiert beziehungsweise verschiebt eine Datei oder ein
Verzeichnis in eine andere Datei unter Beibehaltung der bisherigen
Versionshistory (kein Äquivalent in CVS).

merge

Äquivalent zu »cvs update -j«; es arbeitet
anderswo erstellte Änderungen in die Arbeitskopie ein.

switch

Ändert die Arbeitskopie so, dass sie einen anderen Branch
verwendet.

diff

Zeigt Unterschiede (Diffs) zwischen der Arbeitskopie und den
neuesten, aktualisierten Sources (kein Äquivalent in CVS) oder
dem aktuellen Repository auf.

log

Zeigt Protokolleinträge für eine Ressource an.

propadd, proplist, propdel, propview

Manipuliert die Metadaten zu einer Datei (kein Äquivalent
in CVS). Damit kann man beliebige Daten mit jeder Datei und jedem
Verzeichnis verknüpfen. Einige Metadaten-Schlüssel haben
besondere Bedeutung (zum Beispiel
»svn:mime-type«).

Protokoll-Fragen

Subversion nutzt die WebDAV- und DeltaV-Erweiterungen des HTTP-Protokolls für die Client-Server-Kommunikation. In der Praxis bedeutet dies, dass Apache 2 mit einem speziellen Modul für die Server-Operationen zum Einsatz kommt und dass der Client Standard-HTTP/WebDAV spricht. Damit profitiert Subversion Server-seitig von einem stabilen und hinlänglich getesteten Netzwerkserver.

Mit Apache kommt der SCM kostenlos in den Genuss einiger weiterer nützlicher Features: des »htpasswd«-Mechanismus für die Client-Server-Authentifizierung, der sicheren Client-Server-Kommunikation über »modssl« sowie der Komprimierung via »mod_deflate«. Nicht zuletzt lassen sich Subversion-Repositories ohne zusätzlichen Aufwand über ein Webinterface ansprechen – die User geben einfach die URL des Repository-Root-Verzeichnisses im Browser ein (siehe Abbildung 1).

Dennoch braucht sich in Zukunft niemand Gedanken über die Installation und Verwaltung von Apache machen: Für den Betrieb eines Remote-Subversion-Servers liefert das Subversion-Team einen abgespeckten Stand-alone-Server mit. Er bietet die gleiche Funktionalität wie ein CVS-Pserver. Allerdings wurde er bisher noch nicht systematisch auf Herz und Nieren getestet.

Modulares Design

Als ausgesprochen modulare Client-Server-Applikation besteht Subversion aus einer Reihe von Bibliotheken, von denen jede eine bestimmte Funktion übernimmt, sowie einigen Befehlszeilen-Utilities (Abbildung 2). Im Gegensatz zu CVS ist eine dieser Libraries für alle Client-Operationen zuständig. Um einen grafischen Client zu programmieren, ist es daher nicht notwendig, ein GUI über das bestehende Kommandozeilen-Interface zu stülpen. Er greift stattdessen auf die gleichen, in einer einzigen Bibliothek enthaltenen Funktionen zu wie ein Befehlszeilen-Client.

Gegenwärtig gibt es zwei grafische Clients: einen WX-Windows-basierten namens »rapidSVN« sowie »gsvn«, ein Python-Programm mit GTK+-GUI.

Abbildung 2: Das betont modulare Design von Subversion.

Abbildung 2: Das betont modulare Design von Subversion.

Mahnende Worte

Auch wenn sich Subversion bereits in ernsthaften Projekten bewährt, darf es sich als Alpha-Software noch einige Unzulänglichkeiten leisten. Anders als manch anderer Hersteller machen seine Entwickler auch keinen Hehl aus den noch nicht bewältigten Problemen – es gibt im Gegenteil sogar eine Webseite[5], die die schlimmsten von ihnen auflistet. Damit lassen sich jedoch auch Gründe finden, die gegen die sofortige Umstellung eines Projekts auf Subversion sprechen.

Einer davon ist, dass anders als bei CVS unterbrochene Checkouts derzeit noch neu gestartet werden müssen. Die Behebung dieses Problems steht zwar noch vor Version 1.0 auf dem Plan. Es kann aber genauso gut möglich sein, dass diese Unzulänglichkeit gar nicht stört: Sie kommt meist erst dann zum Tragen, wenn viele User immer wieder zusammenbrechende 56-KBit-Modemverbindungen benutzen.

Ein weiteres Problem besteht darin, dass der Migrationssupport für bestehende CVS-Repositories derzeit noch unvollständig ist. Weil CVS die Versionsverfolgung Datei-bezogen realisiert, lassen sich Branches und Tags, die im Repository als Kopien vorliegen, nur sehr schwer nach Subversion migrieren. Zwar soll auch dieses Problem spätestens in Version 1.0 gelöst sein, aber da es nicht trivial ist …

Die Praxis

Wer sich davon nicht abschrecken lässt, schaut sich Subversion am besten selbst an. Dazu ist ein Subversion-Client erforderlich sowie die Möglichkeit, ein eigenes Repository anzulegen. Zur Speicherung der Dateien im Repository nutzt Subversion das Berkeley-Datenbankformat in Version 4[6].

Debian-User finden Subversion im Unstable-Zweig. Für Red Hat und Mandrake sowie andere RPM-basierte Distributionen bietet die Download-Seite des Projekts vorkompilierte Pakete an. Zudem besteht die Möglichkeit, den Quellcode selbst zu kompilieren. Die neuesten Release-Source-Tarballs stehen unter[7] zur Verfügung. Bei Redaktionsschluss hatte die stabile Version die Nummer 0.20.1, sie basiert auf der Berkeley-DB 4.0.14. Einige Kompilationshinweise bietet Abschnitt II in der Anleitung zur In- stallation[8]; im Wesentlichen dreht sich auch hier wieder alles um den altbekannte Dreiklang »./configure; make; make install«. Etwas komplizierter wird es erst, wenn es um die neueste Entwicklerversion geht, aber auch hier beschreibt die erwähnte Installationsanleitung die nötigen Details.

Eine umfassende Anleitung zum Erstellen des ersten Subversion-Repository finden Sie in der »README«-Datei[9]. Der entscheidende Befehl lautet:

svnadmin create /pfad/zum/repository

Stellen Sie sicher, dass Sie Schreibrechte für das Repository-Verzeichnis besitzen und dass es tatsächlich existiert.

Als Ausgangsbasis empfehlen die Subversion-Entwickler eine Verzeichnisstruktur anzulegen, die Branches und Tags sauber abtrennt (Listing 1). Die Struktur kann später jederzeit ergänzt und geändert werden. Ohne ein passendes System kann es knifflig werden, den Überblick darüber zu behalten, wo ein bestimmtes Tag oder ein Branch abgelegt ist. Daher ist es sinnvoll, alle Repositories auf einer definierten Grundstruktur aufbauen zu lassen.

Viele Wege führen hier nach Rom. Am einfachsten erstellen Sie die Verzeichnisstruktur, wie in Listing 2 gezeigt, und nutzen den »svn«-Import, um diese in einem Rutsch ins Repository aufzunehmen. Anschließend importieren Sie die Sources ins Repository:

cd projekt
svn import file://repository-pfad /trunk/U projekt . -m "Import Projekt-Sources"

Ob das geklappt hat, lässt sich mit Hilfe von

svn co file://repository-pfad/trunk/U projekt svn_projekt

leicht feststellen. Jetzt können Sie die alten Projektquellen entfernen und von nun an mit Subversion arbeiten:

rm -rf projekt
mv svn_projekt projekt

Tabelle 1 gibt einen Überblick über die gängigsten Subversion-Befehle. Der Subversion Quick Guide[12] enthält eine etwas detailliertere Übersicht und das Subversion-Buch[3] bietet eine ausführliche Beschreibung aller verfügbaren Kommandos.

Abbildung 3: Diese Session demonstriert typische Subversion-Befehle wie »status«, »proplist« und »commit«.

Abbildung 3: Diese Session demonstriert typische Subversion-Befehle wie »status«, »proplist« und »commit«.

Listing 1:
Empfohlene Verzeichnisstruktur

01 /
02   trunk
03     projekt
04     projekt2
05   branches
06     projekt
07       // projekt-Branches hier erstellen
08     projekt2
09       // projekt2-Branches hier erstellen
10   tags
11     branches
12       projekt 
13        // projekt-Tags hier erstellen
14              projekt2

Listing 2: Erzeugen
der Basisstruktur

01 mkdir tmp
02 mkdir tmp/trunk tmp/branches tmp/tags
03 mkdir tmp/trunk/projekt tmp/branches/projekt tmp/ tags/branches
04 cd tmp
05 svn import file://repository-pfad . -m  "Verzeichnisstruktur initialisiert"

Apache 2 als Subversion-Netzwerkserver

Für einen Subversion-Netzwerkserver ist Apache 2.0[10] einschließlich APR und APRutil erforderlich, darüber hinaus muss Neon[11] installiert sein. Dabei handelt es sich um jene Implementierung von WebDAV und DeltaV, die der Subversion-Client benötigt, um sich mit Apache auszutauschen. Die zum Zeitpunkt der Veröffentlichung stabile Subversion-Version benötigt Apache in der Version 2.0.44 (oder eine Pre-Release) sowie Neon 0.23.5.

Entpacken Sie Neon in den »svn«-Source-Tree in dem Verzeichnis »neon«, und konfigurieren es mit »–with-apxs = /pfad/zu/apxs«. Wenn Sie nicht mit einem Debug-Build von Apache arbeiten, ist zu beachten, dass Sie Subversion ohne Debug-Flags kompilieren – andernfalls wird das Subversion-Modul nicht laden. Nach Kompilierung und Installation nehmen Sie sich die Apache-Konfigurationsdatei vor, um das »mod_dav_svn«-Modul hinzuzufügen sowie den Speicherort und die Zugriffsmethode für das Repository festzulegen. Anschließend starten Sie Apache.

Ab jetzt sollte der Webbrowser unter [http://localhost/repository] (oder jenem Speicherort, den Sie Apache mitgeteilt haben) den angelegten Source-Tree anzeigen. Wer den Zugriff auf den Quellcode einschränken oder sicheres Tunnelling einrichten will, findet in der Dokumentation zu Apache 2 die entscheidenden Hinweise.

Zusammenfassung

Ohne Zweifel mausert sich Subversion langsam, aber sicher zum natürlichen Nachfolger von CVS. Nach einer Entwicklungszeit von nur rund zweieinhalb Jahren arbeitet der SCM bereits stabil genug, um CVS in Programmierprojekten zu ersetzen.

Dem großflächigen Einsatz stehen aber noch einige Hindernisse im Weg, darunter die Tatsache, dass die Client-Software im Gegensatz zu CVS bislang nicht für alle Plattformen zur Verfügung steht. Zudem fehlen den Migrationstools noch einige Features. (pju)

Infos

[1] Subversion-Homepage: [http://subversion.tigris.org/]

[2] CVS-Homepage: [http://www.cvshome.org/]

[3] Subversion-Buch: [http://svnbook.red-bean.com/book.html]

[4] Subversion-Sources: [http://svn.collab.net/repos/svn/]

[5] Unzulänglichkeiten: [http://subversion.tigris.org/inconveniences.html]

[6] Berkeley-DB-Homepage: [http://www.sleepycat.com/]

[7] Subversion-Downloads: [http://subversion.tigris.org/servlets/ProjectDocumentList]

[8] INSTALL: [http://svn.collab.net/repos/svn/trunk/INSTALL]

[9] README: [http://svn.collab.net/repos/svn/trunk/README]

[10] Apache-2-Homepage: [http://httpd.apache.org/]

[11] Neon-Homepage: [http://www.webdav.org/neon/]

[12] Schnellreferenz: [http://subversion.tigris.org/files/documents/15/177/foo.ps]

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben