Versionskontrolle mit Subversion

Für Subversion 1.5

(Übersetzt aus der Revision 3658)

Ben Collins-Sussman

Brian W. Fitzpatrick

C. Michael Pilato

Dieses Werk steht unter der Lizenz der Creative Commons Attribution License. Um eine Kopie dieser Lizenz einzusehen, gehen Sie zu http://creativecommons.org/licenses/by/2.0/ oder schreiben Sie an Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

(TBA)


Inhaltsverzeichnis

Geleitwort
Vorwort
Publikum
Wie dieses Buch zu lesen ist
Konventionen in diesem Buch
Aufbau dieses Buchs
Dieses Buch ist frei
Danksagungen
Von Ben Collins-Sussman
Von Brian W. Fitzpatrick
Von C. Michael Pilato
Was ist Subversion?
Ist Subversion das richtige Werkzeug?
Die Geschichte von Subversion
Die Architektur von Subversion
Die Komponenten von Subversion
Was gibt es Neues in Subversion
1. Grundlegende Konzepte
Das Repository
Versionierungsmodelle
Das Problem ??The Problem of File Sharing
The Lock-Modify-Unlock Solution
Die „Kopieren – Ändern – Zusammenfassen“ - Lösung
Subversion in Action
Subversion-Repository-URLs
Arbeitskopien
Revisionen
Wie Arbeitskopien das Repository verfolgen
Arbeitskopien mit gemischten Revisionen
Updates und Commits sind getrennt
Gemischte Revisionen sind normal
Gemischte Revisionen sind nützlich
Gemischte Revisionen haben ihre Grenzen
Zusammenfassung
2. Grundlegende Benutzung
Hilfe!
Wie Sie Daten in Ihr Repository bekommen
svn import
Empfohlene Repository Aufteilung
Anfänglicher Checkout
Das Zwischenspeichern des Passwortes abstellen
Authentifizierung als ein anderer Anwender
Der grundlegende Arbeitszyklus
Aktualisieren Sie Ihre Arbeitskopie
Nehmen Sie Änderungen an Ihrer Arbeitskopie vor
Untersuchen Sie Ihre Änderungen
Verschaffen Sie sich einen Überblick über Ihre Änderungen
Untersuchen Sie die Details Ihrer lokalen Änderungen
Zurücknehmen von Änderungen in der Arbeitskopie
Konflikte auflösen (Änderungen anderer einarbeiten)
Interaktive Begutachtung der Konflikte
Interaktive Konfliktauflösung
Aufschieben der Konfliktauflösung
Manuelle Konfliktauflösung
Verwerfen Ihrer Änderungen zugunsten einer aktualisierten Revision aus dem Repository
Die Verwendung von svn revert
Übergeben Ihrer Änderungen
Geschichtsforschung
Erzeugung einer Liste der Änderungsgeschichte
Detaillierte Untersuchung der Änderungsgeschichte
Untersuchen lokaler Änderungen
Vergleichen der Arbeitskopie mit dem Repository
Vergleichen von Repository mit Repository
Stöbern im Repository
svn cat
svn list
Bereitstellung älterer Repository-Schnappschüsse
Manchmal müssen Sie einfach nur aufräumen
Entsorgen einer Arbeitskopie
Wiederherstellung nach einer Unterbrechung
Zusammenfassung
3. Advanced Topics
Revision Specifiers
Revision Keywords
Revision Dates
Properties
Why Properties?
Manipulating Properties
Properties and the Subversion Workflow
Automatic Property Setting
File Portability
File Content Type
File Executability
End-of-Line Character Sequences
Ignoring Unversioned Items
Keyword Substitution
Sparse Directories
Locking
Creating Locks
Discovering Locks
Breaking and Stealing Locks
Lock Communication
Externals Definitions
Peg and Operative Revisions
Changelists
Creating and Modifying Changelists
Changelists As Operation Filters
Changelist Limitations
Network Model
Requests and Responses
Client Credentials Caching
Summary
4. Verzweigen und Zusammenführen
Was ist ein Zweig?
Verwenden von Zweigen
Erzeugen eines Zweiges
Arbeiten mit Ihrem Zweig
Die Schlüsselkonzepte des Verzweigens
Grundlegendes Zusammenführen
Änderungsmengen
Einen Zweig synchron halten
Mergeinfo und Vorschauen
Änderungen rückgängig machen
Zurückholen gelöschter Objekte
Fortgeschrittenes Zusammenführen
Die Rosinen herauspicken
Merge-Syntax: Die vollständige Enthüllung
Zusammenführen ohne Mergeinfo
Mehr über Konflikte beim Zusammenführen
Änderungen blockieren
Protokolle und Anmerkungen, die Zusammenführungen anzeigen
Die Abstammung berücksichtigen oder ignorieren
Zusammenführen und Verschieben
Abblocken von Clients, die Zusammenführungen nicht ausreichend unterstützen
Das abschließende Wort zur Zusammenführungs-Verfolgung
Zweige durchlaufen
Tags
Erzeugen eines einfachen Tags
Erzeugen eines komplexen Tags
Verwaltung von Zweigen
Aufbau des Repositorys
Lebensdauer von Daten
Verbreitete Verzweigungsmuster
Release-Zweige
Funktions-Zweige
Lieferanten-Zweige
Allgemeines Vorgehen für die Verwaltung von Lieferanten-Zweigen
svn_load_dirs.pl
Zusammenfassung
5. Verwaltung des Repositorys
Das Subversion Repository, Definition
Strategien für die Verwendung eines Repositorys
Planung der Organisation Ihres Repositorys
Entscheiden Sie, wo und wie Ihr Repository untergebracht werden soll
Auswahl der Datenspeicherung
Berkeley DB
FSFS
Anlegen und konfigurieren Ihres Repositorys
Anlegen des Repositorys
Erstellen von Repository-Hooks
Konfiguration von Berkeley DB
Repository-Wartung
Der Werkzeugkasten eines Administrators
svnadmin
svnlook
svndumpfilter
svnsync
fsfs-reshard.py
Dienstprogramme von Berkeley DB
Berichtigung des Protokolleintrags
Plattenplatzverwaltung
Wie Subversion Plattenplatz spart
Entfernen unvollendeter Transaktionen
Entfernen unbenutzter Protokolldateien von Berkeley DB
Wiederherstellung von Berkeley DB
Repository-Daten woandershin verschieben
Filtern der Repository-Historie
Repository Replikation
Sicherung des Repositorys
Verwaltung von Repository UUIDs
Verschieben und Entfernen von Repositorys
Zusammenfassung
6. Die Administration eines Subversion-Servers
Überblick
Auswahl einer Serverkonfiguration
Der svnserve-Server
svnserve über SSH
Der Apache HTTP Server
Empfehlungen
svnserve, ein maßgefertigter Server
Der Serverstart
svnserve als Unix-Dienst
svnserve über inetd starten
svnserve über einen Tunnel
svnserve als Dienst unter Windows
Integrierte Authentifikation und Autorisation
Erstellen einer Passwortdatei und festlegen der Authentifizierungsumgebung (Realm)
Setzen von Zugriffsbeschränkungen
Using svnserve with SASL
Authenticating with SASL
SASL encryption
Tunneling over SSH
SSH configuration tricks
Initial setup
Controlling the invoked command
httpd, the Apache HTTP Server
Prerequisites
Basic Apache Configuration
Authentication Options
Setting up HTTP authentication
SSL certificate management
Authorization Options
Blanket access control
Per-directory access control
Disabling path-based checks
Extra Goodies
Repository browsing
Apache logging
Write-through proxying
Other Apache features
Path-Based Authorization
Supporting Multiple Repository Access Methods
7. Subversion an Ihre Bedürfnisse anpassen
Laufzeit-Konfigurationsbereich
Aufbau des Konfigurationsbereichs
Konfiguration und die Windows-Registrierungsdatenbank
Konfigurationsoptionen
Servers
Config
Lokalisierung
Locales verstehen
Wie Subversion Locales verwendet
Verwendung externer Editoren
Verwenden externer Vergleichs- und Zusammenführungsprogramme
Externes diff
Externes diff3
Zusammenfassung
8. Subversion integrieren
Schichtenmodell der Bibliotheken
Repository-Schicht
Repository-Zugriffs-Schicht
Client-Schicht
Innerhalb des Verwaltungsbereichs für Arbeitskopien
Die Datei entries
Unveränderte Kopien und Property-Dateien
Benutzung der APIs
Die Bibliothek Apache Portable Runtime
URL- und Pfadanforderungen
Verwendung anderer Sprachen als C und C++
Beispielcode
Zusammenfassung
9. Die komplette Subversion Referenz
Der Kommandozeilen-Client von Subversion: svn
svn-Optionen
svn-Unterbefehle
svn add
svn blame
svn cat
svn changelist
svn checkout
svn cleanup
svn commit
svn copy
svn delete
svn diff
svn export
svn help
svn import
svn info
svn list
svn lock
svn log
svn merge
svn mergeinfo
svn mkdir
svn move
svn propdel
svn propedit
svn propget
svn proplist
svn propset
svn resolve
svn resolved
svn revert
svn status
svn switch
svn unlock
svn update
svnadmin
svnadmin-Optionen
svnadmin-Unterbefehle
svnadmin crashtest
svnadmin create
svnadmin deltify
svnadmin dump
svnadmin help
svnadmin hotcopy
svnadmin list-dblogs
svnadmin list-unused-dblogs
svnadmin load
svnadmin lslocks
svnadmin lstxns
svnadmin recover
svnadmin rmlocks
svnadmin rmtxns
svnadmin setlog
svnadmin setrevprop
svnadmin setuuid
svnadmin upgrade
svnadmin verify
svnlook
svnlook Optionen
svnlook Unterbefehle
svnlook author
svnlook cat
svnlook changed
svnlook date
svnlook diff
svnlook dirs-changed
svnlook help
svnlook history
svnlook info
svnlook lock
svnlook log
svnlook propget
svnlook proplist
svnlook tree
svnlook uuid
svnlook youngest
svnsync
svnsync Optionen
svnsync-Unterbefehle
svnsync copy-revprops
svnsync help
svnsync initialize
svnsync synchronize
svnserve
svnserve-Optionen
svndumpfilter
svndumpfilter-Optionen
svndumpfilter-Unterbefehle
svndumpfilter exclude
svndumpfilter include
svndumpfilter help
svnversion
svnversion
mod_dav_svn
mod_dav_svn-Konfigurationsanweisungen
mod_authz_svn
mod_authz_svn-Konfigurationsanweisungen
Subversion-Propertys
Versionierte Propertys
Unversionierte Propertys
Repository-Hooks
start-commit
pre-commit
post-commit
pre-revprop-change
post-revprop-change
pre-lock
post-lock
pre-unlock
post-unlock
A. Subversion-Einführung für einen schnellen Stert
Subversion installieren
Schnellstart-Lehrgang
B. Subversion für CVS-Benutzer
Revisionsnummern sind jetzt anders
Directory Versions
More Disconnected Operations
Distinction Between Status and Update
Status
Update
Branches and Tags
Metadata Properties
Conflict Resolution
Binary Files and Translation
Versioned Modules
Authentication
Converting a Repository from CVS to Subversion
C. WebDAV and Autoversioning
What Is WebDAV?
Autoversioning
Client Interoperability
Standalone WebDAV Applications
Microsoft Office, Dreamweaver, Photoshop
cadaver, DAV Explorer
File-Explorer WebDAV Extensions
Microsoft Web Folders
Nautilus, Konqueror
WebDAV Filesystem Implementation
WebDrive, NetDrive
Mac OS X
Linux davfs2
D. Copyright
Stichwortverzeichnis

Abbildungsverzeichnis

1. Die Architektur von Subversion
1.1. Ein typisches Client/Server System
1.2. The problem to avoid
1.3. Die Sperren - Ändern - Entsperren - Lösung veranschaulicht diese einfache Möglichkeit
1.4. „Kopieren – Ändern – Zusammenfassen“ - Lösung
1.5. „Kopieren – Ändern – Zusammenfassen“ - Lösung (Fortsetzung)
1.6. Das Dateisystem des Repositorys
1.7. Das Repository
4.1. Entwicklungszweige
4.2. Repository-Struktur zu Beginn
4.3. Repository mit neuer Kopie
4.4. Die Verzweigung der Geschichte einer Datei
8.1. Dateien und Verzeichnisse in zwei Dimensionen
8.2. Versionierung der Zeit – die dritte Dimension!

Tabellenverzeichnis

1.1. Repository-Zugriffs-URLs
4.1. Befehle zum Verzweigen und Zusammenführen
5.1. Vergleich der Repository-Datenspeicherung
6.1. Vergleich der Serveroptionen für Subversion
C.1. Common WebDAV clients

Beispiele

5.1. txn-info.sh (ausstehende Transaktionen anzeigen)
5.2. pre-revprop-change-Hook-Script des Spiegel-Repositorys
5.3. start-commit-Hook-Script des Spiegel-Repositorys
6.1. A sample configuration for anonymous access
6.2. A sample configuration for authenticated access
6.3. A sample configuration for mixed authenticated/anonymous access
6.4. Disabling path checks altogether
7.1. Beispieldatei mit Einträgen für die Registrierungsdatenbank (.reg)
7.2. diffwrap.py
7.3. diffwrap.bat
7.4. diff3wrap.py
7.5. diff3wrap.bat
8.1. Verwendung der Repository-Schicht
8.2. Verwendung der Repository-Schicht mit Python
8.3. Status in Python

Geleitwort

Karl Fogel

Chicago, 14, März 2004.

Eine schlechte FAQ (Frequently Asked Questions) ist eine, die nicht aus den Fragen besteht, die wirklich gefragt wurden, sondern aus denen, die der Autor sich von den Fragenden gewünscht hätte. Vielleicht haben Sie solche schon gesehen:

F: Wie kann ich Glorbosoft XYZ einsetzen, um die Team-Produktivität zu maximieren?

A: Viele unserer Kunden wollen wissen, wie sie Ihre Produktivität mit unseren patentierten Office Groupware Innovationen maximieren können. Die Antwort ist einfach: zuerst klicken Sie auf das Menü Datei, fahren hinunter zum Eintrag Erhöhe Produktivität, und dann …

Das Problem mit solchen FAQs ist, dass sie keine FAQs im eigentlichen Sinne sind. Niemand fragt den technischen Support: Wie können wir unsere Produktivität steigern? Üblicherweise fragen Leute sehr spezifische Fragen, wie: Wie können wir das Kalendersystem so ändern, dass es die Erinnerungen zwei Tage statt einen Tag im Voraus aussendet? und so weiter. Aber es ist viel leichter, häufig gestellte Fragen zu erfinden, als die richtigen Fragen zu entdecken. Eine sinnvolle FAQ-Sammlung zusammenzustellen, erfordert eine ausdauernde, planvolle Anstrengung: über die Lebensdauer einer Software müssen hereinkommende Anfragen ausgewertet und Rückmeldungen evaluiert werden und zu einem konsistenten und benutzerfreundlichen Ganzen zusammengeführt werden, das die gesammelte Erfahrung der Anwendenden wiedergibt. Es erfordert die geduldige, aufmerksame Einstellung eines Naturforschers. Nicht großartige Hypothesen und visionäre Vorhersagen, sondern hauptsächlich offene Augen und genaue Aufzeichnungen sind gefragt.

Was ich an diesem Buch liebe, ist, dass es genau aus einem solchen Prozess gewachsen ist und dies auf jeder Seite sichtbar ist. Es ist das direkte Ergebnis der Begegnungen der Autoren mit Benutzern. Es begann mit Ben Collins-Sussmans Beobachtung, dass Leute immer wieder die gleichen grundlegenden Fragen auf der Subversion-Mailingliste stellten: Was sind die Standard-Arbeitsabläufe mit Subversion? Funktionieren Branches und Tags genau so wie in anderen Versionskontrollsystemen? Wie finde ich heraus, wer eine bestimmte Änderung durchgeführt hat?

Frustriert davon, Tag für Tag immer wieder die gleichen Fragen zu sehen, arbeitete Ben im Sommer 2002 über einen Monat intensiv daran, The Subversion Handbook zu schreiben, eine 60-seitige Anleitung, die die Grundlagen der Benutzung von Subversion beschrieb. Die Anleitung erhob keinen Anspruch auf Vollständigkeit, aber sie wurde mit Subversion verteilt und half vielen über die ersten Buckel der Lernkurve. Als O'Reilly and Associates sich entschieden, ein vollständiges Buch über Subversion herauszugeben, war der Weg des geringsten Widerstandes offensichtlich: The Subversion Handbook muss erweitert werden.

Die drei Co-Autoren des neuen Buches erhielten somit eine seltene Gelegenheit. Eigentlich war es ihre Aufgabe, ein Buch beginnend mit dem Inhaltsverzeichnis und einem Rohkonzept zu schreiben; jedoch hatten sie auch Zugang zu einem ständigen Strom – ja einem unkontrollierbaren Geysir – aus Quellmaterial. Subversion wurde bereits von tausenden experimentierfreudigen Menschen benutzt, und diese gaben Unmengen an Rückmeldungen – nicht nur über Subversion, sondern auch über die bestehende Dokumentation.

Während der gesamten Zeit, in der sie dieses Buch schrieben, durchstöberten Ben, Mike und Brian unablässig die Subversion-Mailinglisten und Chaträume und notierten die Probleme, die Benutzer im echten Leben hatten. Die Beobachtung derartiger Rückmeldungen war ohnehin ein Teil ihrer Arbeit bei CollabNet, was ihnen einen Riesenvorteil verschaffte, als sie sich entschlossen, Subversion zu dokumentieren. Das Buch, das sie schrieben, gründet auf dem festen Fels der Erfahrung und nicht auf dem Treibsand des Wunschdenkens. Es vereint die Vorteile von Bedienungsanleitung und FAQ. Diese Zweigleisigkeit ist vielleicht nicht gleich zu erkennen. Von vorne nach hinten gelesen ist das Buch einfach eine Beschreibung einer Software. Es gibt die Übersicht, den obligatorischen Rundgang, das Kapitel über Administration, einige fortgeschrittene Themen und natürlich eine Funktionsübersicht sowie eine Anleitung zur Problemlösung. Erst wenn Sie es später wieder zur Hand nehmen, um die Lösung für ein bestimmtes Problem zu suchen, wird die Zuverlässigkeit des Buches offenbar: in den beschriebenen Details,die nur aus der Erfahrung mit dem Unerwarteten erwachsen konnten, in den Beispielen, die aus dem tatsächlichem Einsatz gebildet wurden, und am meisten durch das Gefühl für die Bedürfnisse und den Blickwinkel der Benutzer.

Natürlich kann niemand versprechen, dass dieses Buch alle Fragen beantwortet, die Sie über Subversion haben. Manchmal wird die Genauigkeit, mit der es Ihre Fragen erwartet, unheimlich und telepathisch erscheinen; gelegentlich werden Sie jedoch in ein Loch im Wissen der Gemeinschaft stolpern und mit leeren Händen dastehen. Wenn das passiert schreiben Sie am besten eine E-Mail an und schildern Ihr Problem. Die Autoren sind nach wie vor dort und beobachten. Und das betrifft nicht nur die drei, die auf dem Umschlag erscheinen sind, sondern viele andere, die Korrekturen und neues Material beigesteuert haben. Aus der Sicht der Gemeinschaft ist die Lösung Ihres Problems lediglich ein erfreulicher Nebeneffekt eines viel größeren Projektes – nämlich das Buch und schlussendlich auch Subversion selbst immer näher an die Art und Weise anzupassen, in der es tatsächlich benutzt wird. Diese Personen sind begierig darauf, von Ihnen zu hören, nicht nur weil sie Ihnen helfen können, sondern auch weil ihnen selbst damit geholfen ist. Für Subversion – so wie für alle aktiven freien Software-Projekte – gilt: Sie sind nicht allein.

Lassen Sie dieses Buch Ihren ersten Begleiter sein.

Vorwort

 

Es ist wichtig, die Vollkommenheit nicht zum Feind des Guten werden zu lassen, selbst dann, wenn darüber Einigkeit besteht, was Vollkommenheit ist. Erst recht, wenn man sich nicht darüber einig ist. So unangenehm es ist, durch vergangene Fehler gefangen zu sein, kann man während des Entwurfs keinen Fortschritt erzielen, wenn man Angst vor dem eigenen Schatten hat.

 
 --Greg Hudson, Subversion-Entwickler

In der Welt der Open-Source-Software war das Concurrent Versions System (CVS) für viele Jahre das Werkzeug der Wahl für Versionskontrolle. Und das zu Recht. CVS war selbst Open-Source-Software und seine nicht-einschränkende Vorgehensweise und Unterstützung für netzbasierten Einsatz erlaubte dutzenden geografisch verteilten Programmierern, ihre Arbeit zu teilen. Es passte sehr gut zur kollaborativen Natur der Open-Source-Welt. CVS und sein halb chaotisches Entwicklungsmodell sind seitdem zu Eckpfeilern der Open-Source-Kultur geworden.

Jedoch war CVS nicht makellos, und diese Makel einfach zu beseitigen, versprach einen enormen Aufwand. Bühne frei für Subversion. Subversion wurde als Nachfolger für CVS entworfen, und seine Schöpfer zogen los, um auf zwei Wegen die Herzen der CVS-Benutzer zu gewinnen – indem ein Open-Source-System erschaffen wurde, dessen Design (und look and feel) ähnlich wie CVS war, und indem versucht wurde, die auffälligsten Makel von CVS zu vermeiden. Obwohl das Ergebnis nicht notwendigerweise den nächsten Evolutionsschritt in Sachen Versionskontrolle darstellt, ist Subversion sehr mächtig, sehr brauchbar und sehr flexibel. Und größtenteils wählen nun fast alle neuen Open-Source-Projekte Subversion statt CVS.

Dieses Buch ist geschrieben worden, um die Serie 1.5 des Subversion Versionskontrollsystems zu dokumentieren. Wir haben stets versucht, die Themen gründlich zu behandeln. Jedoch hat Subversion eine florierende und tatkräftige Entwicklergemeinde, so dass bereits eine Menge an Features und Verbesserungen für künftige Versionen von Subversion geplant sind, die Änderungen mancher Kommandos und bestimmter Anmerkungen in diesem Buch bewirken könnten.

Publikum

Dieses Buch ist für computerkundige Leute geschrieben, die mit Subversion ihre Daten verwalten wollen. Obwohl Subversion unter verschiedenen Betriebssystemen läuft, ist die primäre Benutzerschnittstelle kommandozeilenbasiert. Dieses Kommandozeilenwerkzeug (svn) und einige Hilfsprogramme stehen im Mittelpunkt dieses Buches.

Aus Gründen der Vereinheitlichung gehen die Beispiele in diesem Buch davon aus, dass der Leser ein unixähnliches Betriebssystem benutzt und mit Unix und Kommandozeilenschnittstellen verhältnismäßig gut zurechtkommt. Nichtsdestotrotz läuft svn auch unter anderen Betriebssystemen als Unix, etwa Microsoft Windows. Bis auf ein paar Ausnahmen, wie z.B. die Verwendung umgekehrter Schrägstriche (\) statt Schrägstrichen (/) als Pfadtrenner, sind die Ein- und Ausgaben dieses Werkzeugs unter Windows identisch zur Unix-Version.

Die meisten Leser sind wahrscheinlich Programmierer oder Systemadministratoren, die Änderungen an Quellcode verfolgen müssen. Das ist der am meisten verbreitete Einsatzzweck von Subversion, so dass alle Beispiele in diesem Buch auf diesem Szenario beruhen. Doch Subversion kann gleichwohl dazu benutzt werden, Änderungen an allerlei Arten von Informationen zu verwalten – Bilder, Musik, Datenbanken, Dokumentation usw. Für Subversion sind alle Daten einfach Daten.

Obwohl dieses Buch unter der Annahme geschrieben worden ist, dass der Leser noch nie ein Versionskontrollsystem benutzt hat, haben wir auch versucht, für Anwender von CVS (und anderen Systemen) den Sprung zu Subversion so schmerzlos wie möglich zu machen. Ab und zu werden in Randnotizen andere Versionskontrollsysteme erwähnt, und ein besonderer Anhang fasst viele der Unterschiede zwischen CVS und Subversion zusammen.

Es sei angemerkt, dass es sich bei den Quelltexten in diesem Buch nur um Beispiele handelt. Obwohl sie sich mit den passenden Compiler-Aufrufen übersetzen ließen, sollen sie lediglich ein besonderes Szenario illustrieren und nicht als Vorlage für guten Programmierstil oder gute Programmierpraxis dienen.

Wie dieses Buch zu lesen ist

Technische Bücher stehen immer vor einem bestimmten Dilemma: ob sie von-oben oder von-unten Lernenden entgegenkommen sollen. Ein von-oben Lernender bevorzugt es, Dokumentation zu lesen oder zu überfliegen und dabei einen groben Überblick über das Funktionieren des Systems zu erhalten, bevor er beginnt, die Software zu verwenden. Ein von-unten Lernender ist eine Person, für die Lernen durch Ausprobieren gilt, jemand, der in die Software eintauchen möchte, um beim Ausprobieren herauszufinden, wie sie funktioniert, und wenn nötig Abschnitte im Buch nachschlägt. Die meisten Bücher werden für die eine oder andere Art dieser Personen geschrieben, wobei dieses Buch zweifellos den von-oben Lernenden entgegenkommt. (Und wenn Sie gerade diesen Abschnitt lesen, sind Sie wahrscheinlich selber ein von-oben Lernender!) Verzweifeln Sie jedoch nicht, falls Sie ein von-unten Lerner sind. Während dieses Buch als eine breite Betrachtung der Themen rund um Subversion gestaltet ist, beinhaltet jeder Abschnitt eine reichhaltige Auswahl an Beispielen, die sie ausprobieren können. Die Ungeduldigen, die einfach weitermachen wollen, können sofort zu Anhang A, Subversion-Einführung für einen schnellen Stert springen.

Ungeachtet Ihrer Lernmethode zielt dieses Buch darauf ab, für Menschen unterschiedlicher Herkunft nützlich zu sein – von Menschen ohne vorherige Erfahrung mit Versionskontrolle bis hin zu erfahrenen Systemadministratoren. Je nach Ihrer Herkunft können bestimmte Kapitel mehr oder weniger wichtig für Sie sein. Was nun folgt, kann als Leseempfehlung für verschiedene Typen von Lesern betrachtet werden:

Erfahrene Systemadministratoren

Die Annahme ist, dass Sie wahrscheinlich bereits Versionskontrolle verwendet haben und darauf brennen, möglichst schnell einen Subversion-Server zum Laufen zu bekommen. Kapitel 5, Verwaltung des Repositorys und Kapitel 6, Die Administration eines Subversion-Servers zeigen, wie Sie Ihr erstes Repository erzeugen und es über das Netz verfügbar machen können. Danach sind Kapitel 2, Grundlegende Benutzung und Anhang B, Subversion für CVS-Benutzer die schnellsten Wege zum Lernen des Subversion-Clients.

Neulinge

Wahrscheinlich hat Ihr Administrator Subversion bereits aufgesetzt, und Sie möchten nun lernen, wie man den Client benutzt. Falls Sie noch nie ein Versionskontrollsystem benutzt haben, ist Kapitel 1, Grundlegende Konzepte eine unbedingt notwendige Einführung in die Konzepte der Versionskontrolle. Kapitel 2, Grundlegende Benutzung ist eine Führung durch den Subversion-Client.

Fortgeschrittene

Ob Sie ein Benutzer oder ein Administrator sind, letztendlich wird Ihr Projekt anwachsen. Sie werden lernen wollen, wie man fortgeschrittene Dinge mit Subversion machen kann, etwa Zweige verwenden und Zusammenführungen durchführen (Kapitel 4, Verzweigen und Zusammenführen), wie Subversions Property-Unterstützung (Kapitel 3, Advanced Topics) zu benutzen ist, wie Laufzeitoptionen konfiguriert werden können (Kapitel 7, Subversion an Ihre Bedürfnisse anpassen) und vieles mehr. Diese Kapitel sind zunächst nicht kritisch, jedoch sollten Sie sie lesen, sobald Sie mit den Grundlagen vertraut sind.

Entwickler

Unter der Annahme, dass Sie bereits mit Subversion vertraut sind und es nun entweder erweitern oder neue Software basierend auf einem seiner zahlreichen APIs erstellen möchten, ist Kapitel 8, Subversion integrieren genau das, was sie suchen.

Das Buch schließt mit einer Referenz – Kapitel 9, Die komplette Subversion Referenz ist ein Referenzhandbuch für alle Befehle von Subversion, und die Anhänge behandeln eine Anzahl nützlicher Themen. Dies sind die Kapitel, zu denen Sie sehr wahrscheinlich zurückkehren werden, wenn Sie dieses Buch beendet haben.

Konventionen in diesem Buch

Die folgenden typografischen Konventionen werden in diesem Buch verwendet:

Festbreitenschrift

Verwendet für Benutzereingaben, Befehlsausgaben und Kommandozeilenoptionen

Kursiv

Verwendet für Programm- und Subversion-Unterbefehlsnamen, Datei- und Verzeichnisnamen und für neue Begriffe

Kursive Festbreitenschrift

Verwendet für zu ersetzende Objekte in Code und Text

Des Weiteren haben wir besonders hilfreiche oder wichtige Informationshäppchen, wegen der besseren Auffindbarkeit optisch hervorgehoben, über das gesamte Buch verteilt (dort, wo es für den Zusammenhang bedeutsam ist). Achten Sie beim Lesen auf die folgenden Bilder:

[Anmerkung]Anmerkung

Dieses Bild markiert einen besonders wichtigen Punkt.

[Tipp]Tipp

Dieses Bild markiert einen nützlichen Tipp oder eine empfohlene Vorgehensweise.

[Warnung]Warnung

Dieses Bild markiert eine Warnung. Beachten Sie diese besonders, um Probleme zu vermeiden!

Aufbau dieses Buchs

Hier sind die folgenden Kapitel und ihr Inhalt aufgeführt:

Kapitel 1, Grundlegende Konzepte

Erklärt die Grundlagen von Versionskontrolle und unterschiedliche Versionierungsmodelle sowie das Repository von Subversion, Arbeitskopien und Revisionen.

Kapitel 2, Grundlegende Benutzung

Ein Spaziergang durch den Tag eines Subversion-Anwenders. Es zeigt, wie ein Subversion-Client verwendet wird, um Daten zu bekommen, zu verändern und abzuliefern.

Kapitel 3, Advanced Topics

Behandelt komplexere Eigenschaften, denen Benutzer letztendlich begegnen werden, wie etwa versionierte Metadaten, Dateisperren und Peg-Revisionen.

Kapitel 4, Verzweigen und Zusammenführen

Behandelt Zweige, Zusammenführungen und Etikettieren inklusive empfohlener Vorgehensweisen beim Verzweigen und Zusammenführen, übliche Szenarien, wie Änderungen wieder rückgängig gemacht werden können und wie einfach von einem Zweig zum nächsten gewechselt werden kann.

Kapitel 5, Verwaltung des Repositorys

Beschreibt die Grundlagen des Subversion-Repositorys, wie man ein Repository anlegt, konfiguriert und wartet sowie die Tools, die man hierfür benutzen kann

Kapitel 6, Die Administration eines Subversion-Servers

Erklärt, wie man einen Subversion-Server konfiguriert und unterschiedliche Arten auf ein Repository zuzugreifen: HTTP, das svn-Protokoll und über die lokale Festplatte. Behandelt werden hier auch die Authentifizierung, die Autorisierung und der anonyme Zugriff.

Kapitel 7, Subversion an Ihre Bedürfnisse anpassen

Untersucht die Subversion-Client-Konfigurationsdateien, die Handhabung internationalisierter Texte und wie man externe Tools zur Zusammenarbeit mit Subversion bringt.

Kapitel 8, Subversion integrieren

Beschreibt die Interna von Subversion, das Subversion-Dateisystem und die Verwaltungsbereiche der Arbeitskopie aus der Sicht eines Programmierers. Hier wird auch gezeigt, wie die veröffentlichten APIs in einem Programm verwendet werden, das Subversion benutzt.

Kapitel 9, Die komplette Subversion Referenz

Erklärt detailreich jeden Unterbefehl von svn, svnadmin und svnlook mit vielen Beispielen für die ganze Familie.

Anhang A, Subversion-Einführung für einen schnellen Stert

Für die Ungeduldigen eine Anleitung im Schnelldurchlauf für die Installation und die sofortige Benutzung. Seien Sie gewarnt!

Anhang B, Subversion für CVS-Benutzer

Behandelt die Ähnlichkeiten und Unterschiede zwischen Subversion und CVS mit etlichen Vorschlägen, wie man sich all die schlechten Angewohnheiten aus jahrelangem CVS-Gebrauch wieder abgewöhnen kann. Dies beinhaltet Subversion-Revisionsnummern, versionierte Verzeichnisse, Offline-Tätigkeiten, update und status, Zweige, Tags, Metadaten, Konfliktauflösung und Authentifizierung.

Anhang C, WebDAV and Autoversioning

Beschreibt die Details zu WebDAV und DeltaV und wie man sein Subversion-Repository konfiguriert, damit es als freigegebenes DAV-Laufwerk schreibbar in das Dateisystem eingehängt werden kann.

Anhang D, Copyright

Eine Kopie der Creative Commons Attribution License, unter der dieses Buch lizenziert ist.

Dieses Buch ist frei

Dieses Buch startete aus Dokumentationsschnipseln von Entwicklern des Subversion-Projektes, die in einem Werk gebündelt und umgeschrieben wurden. Insofern war es immer schon unter einer freien Lizenz (siehe Anhang D, Copyright). Tatsächlich wurde das Buch unter den Augen der Öffentlichkeit geschrieben, ursprünglich als Teil des Subversion Projektes selbst. Das bedeutet zweierlei:

  • Sie werden stets die neueste Version dieses Buchs im eigenen Subversion-Repository finden.

  • Sie können an diesem Buch Änderungen vornehmen und es wie auch immer weiter verteilen – es unterliegt einer freien Lizenz. Ihre einzige Verpflichtung besteht darin, den Hinweis auf die ursprünglichen Autoren beizubehalten. Natürlich würden wir es bevorzugen, wenn Sie Rückmeldungen und Verbesserungen der Subversion-Entwicklergemeinde zukommen ließen, anstatt Ihre Privatversion zu verteilen.

Die Homepage der Entwicklungs- und Übersetzungsaktivitäten auf freiwilliger Basis ist http://svnbook.red-bean.com. Dort finden Sie Links auf die neuesten Releases und mit Tags versehene Versionen des Buchs in verschiedenen Formaten ebenso wie eine Anleitung, auf das Subversion-Repository des Buchs zuzugreifen (dort lebt sein Quellcode im DocBook-XML-Format). Rückmeldungen sind willkommen – ja sogar erwünscht. Bitte senden Sie alle Kommentare, Beschwerden und Patches für die Sourcen des Buchs an .

Danksagungen

Dieses Buch wäre nicht möglich (und auch nicht sehr nützlich) wenn es Subversion nicht gäbe. Dafür möchten die Autoren Brian Behrendorf danken sowie CollabNet für die Vision, solch ein riskantes und ehrgeiziges Open-Source-Projekt zu finanzieren; Jim Blandy für den ursprünglichen Namen von Subversion und sein Design – wir lieben Dich, Jim; Karl Fogel, dafür, dass er so ein guter Freund und Leiter der Gemeinde ist, in dieser Reihenfolge. [1]

Dank an O'Reilly und unsere verschiedenen Redakteure: Chuck Toporek, Linda Mui, Tatiana Apandi, Mary Brady und Mary Treseler. Ihre Geduld und Unterstützung waren enorm.

Schließlich danken wir den zahllosen Menschen, die zu diesem Buch durch informelle Rezensionen, Vorschläge, und Fehlerbehebungen beigetragen haben. Obwohl diese Liste zweifellos nicht vollständig ist, wäre dieses Buch unfertig und fehlerhaft ohne die Hilfe von: Bhuvaneswaran A, David Alber, C. Scott Ananian, David Anderson, Ariel Arjona, Seth Arnold, Jani Averbach, Charles Bailey, Ryan Barrett, Francois Beausoleil, Brian R. Becker, Yves Bergeron, Karl Berry, Jennifer Bevan, Matt Blais, Jim Blandy, Phil Bordelon, Sietse Brouwer, Tom Brown, Zack Brown, Martin Buchholz, Paul Burba, Sean Callan-Hinsvark, Branko Cibej, Archie Cobbs, Jason Cohen, Ryan Cresawn, John R. Daily, Peter Davis, Olivier Davy, Robert P. J. Day, Mo DeJong, Brian Denny, Joe Drew, Markus Dreyer, Nick Duffek, Boris Dusek, Ben Elliston, Justin Erenkrantz, Jens M. Felderhoff, Kyle Ferrio, Shlomi Fish, Julian Foad, Chris Foote, Martin Furter, Vlad Georgescu, Peter Gervai, Dave Gilbert, Eric Gillespie, David Glasser, Marcel Gosselin, Lieven Govaerts, Steve Greenland, Matthew Gregan, Tom Gregory, Maverick Grey, Art Haas, Mark E. Hamilton, Eric Hanchrow, Liam Healy, Malte Helmert, Michael Henderson, Øyvind A. Holm, Greg Hudson, Alexis Huxley, Auke Jilderda, Toby Johnson, Jens B. Jorgensen, Tez Kamihira, David Kimdon, Mark Benedetto King, Robert Kleemann, Erik Kline, Josh Knowles, Andreas J. Koenig, Axel Kollmorgen, Nuutti Kotivuori, Kalin Kozhuharov, Matt Kraai, Regis Kuckaertz, Stefan Kueng, Steve Kunkee, Scott Lamb, Wesley J. Landaker, Benjamin Landsteiner, Vincent Lefevre, Morten Ludvigsen, Dennis Lundberg, Paul Lussier, Bruce A. Mah, Jonathon Mah, Karl Heinz Marbaise, Philip Martin, Feliciano Matias, Neil Mayhew, Patrick Mayweg, Gareth McCaughan, Craig McElroy, Simon McKenna, Christophe Meresse, Jonathan Metillon, Jean-Francois Michaud, Jon Middleton, Robert Moerland, Marcel Molina Jr., Tim Moloney, Alexander Mueller, Tabish Mustufa, Christopher Ness, Roman Neuhauser, Mats Nilsson, Greg Noel, Joe Orton, Eric Paire, Dimitri Papadopoulos-Orfanos, Jerry Peek, Chris Pepper, Amy Lyn Pilato, Kevin Pilch-Bisson, Hans Polak, Dmitriy Popkov, Michael Price, Mark Proctor, Steffen Prohaska, Daniel Rall, Srinivasa Ramanujan, Jack Repenning, Tobias Ringstrom, Jason Robbins, Garrett Rooney, Joel Rosdahl, Christian Sauer, Ryan Schmidt, Jochem Schulenklopper, Jens Seidel, Daniel Shahaf, Larry Shatzer, Danil Shopyrin, Erik Sjoelund, Joey Smith, W. Snyder, Stefan Sperling, Robert Spier, M. S. Sriram, Russell Steicke, David Steinbrunner, Sander Striker, David Summers, Johan Sundstroem, Ed Swierk, John Szakmeister, Arfrever Frehtes Taifersar Arahesis, Robert Tasarz, Michael W. Thelen, Mason Thomas, Erik van der Kolk, Joshua Varner, Eric Wadsworth, Chris Wagner, Colin Watson, Alex Waugh, Chad Whitacre, Andy Whitcroft, Josef Wolf, Luke Worth, Hyrum Wright, Blair Zajac, Florian Zumbiehl, und die gesamte Subversion Gemeinde.

Von Ben Collins-Sussman

Dank meiner Frau Frances, die sich viele Monate lang Aber, Schatz, ich arbeite noch am Buch anhören musste, statt des üblichen Aber, Schatz ich bearbeite noch E-Mail. Ich weiß nicht, woher sie all die Geduld nimmt. Sie ist der perfekte Ausgleich für mich.

Dank meiner Verwandtschaft und meinen Freunden für ihre aufrichtige Ermutigung, obwohl sie kein tatsächliches Interesse an der Materie hatten. (Sie wissen schon, diejenigen, die sagen Oh, du hast ein Buch geschrieben?, und wenn man ihnen erzählt, es sei ein Computerbuch, die Nase rümpfen.

Vielen Dank an meine engen Freunde, die aus mir einen sehr reichen Mann machen. Schaut mich nicht so an – Ihr wisst, wer Ihr seid.

Dank an meine Eltern für die perfekte Grundformatierung und dafür, dass sie unglaubliche Leitbilder sind. Dank an meine Kinder, für die Gelegenheit, dieses weiterzugeben.

Von Brian W. Fitzpatrick

Einen riesigen Dank an meine Frau Marie dafür, dass sie so unglaublich verständnisvoll, unterstützend und vor allem so geduldig ist. Dank an meinen Bruder Eric, der mich vor langer Zeit als erster an die Programmierung unter UNIX herangeführt hat. Dank an meine Mutter und Großmutter für ihre Unterstützung; ganz zu schweigen davon, dass sie ein Weihnachtsfest ertragen mussten, an dem ich nach Hause kam und sofort meinen Kopf hinter dem Laptop versteckte, um am Buch zu arbeiten.

An Mike und Ben: Es war ein Vergnügen, mit Euch am Buch zu arbeiten. Verdammt, es ist eine Freude mit Euch auf der Arbeit zusammenzuarbeiten.

Dank an alle in der Subversion-Gemeinde und der Apache Software Foundation, dafür, dass ihr mich in euren Bann gezogen habt. Kein Tag vergeht, ohne dass ich irgendetwas von mindestens einem von Euch lerne.

Schließlich Dank an meinen Großvater, der mir immer sagte Freiheit bedeutet Verantwortung. Ich muss dem voll und ganz zustimmen.

Von C. Michael Pilato

Besonderen Dank an Amy, meiner besten Freundin und Ehefrau seit mehr als zehn unglaublichen Jahren, für ihre Liebe und geduldige Unterstützung, dafür, dass sie sich mit den langen Nächten abfand und gnädig die Versionskontrollprozesse ertrug, die ich ihr aufbürdete. Keine Sorge, Liebling – binnen kurzer Zeit wirst du eine TortoiseSVN-Expertin sein.

Gavin, du kannst jetzt die Hälfte der Worte in diesem Buch selber lesen; leider liefert die andere Hälfte die Schlüsselkonzepte. Tut mir Leid, Aidan – ich habe keine Möglichkeit gefunden, Disney/Pixar-Figuren in diesen Text einzuarbeiten. Aber Daddy liebt Euch beide und kann kaum erwarten, Euch das Programmieren beizubringen.

Mutter und Vater, Dank für Eure stetige Unterstützung und Begeisterung. Schwiegereltern, Dank für dasselbe plus Eure sagenhafte Tochter.

Hut ab vor Shep Kendall, der mir als erster die Welt der Computer eröffnete; Ben Collins-Sussman, mein Reiseführer durch die Open-Source-Welt; Karl Fogel – Du bist mein .emacs; Greg Stein, für überquellendes praktisches Programmierwissen; und Brian Fitzpatrick – dafür, dass Du diese Schreiberfahrung mit mir teilst. Vor all den vielen Leuten, von denen ich ständig etwas neues aufnehme – lasst weiter etwas fallen!

Schließlich, vor demjenigen, der perfekt kreative Exzellenz demonstriert – Dank an Dich.

Was ist Subversion?

Subversion ist ein freies/Open-Source Versionskontrollsystem. Das bedeutet, Subversion verwaltet Dateien und Verzeichnisse und die Änderungen an ihnen im Lauf der Zeit. Das erlaubt Ihnen, alte Versionen Ihrer Daten wiederherzustellen oder die Geschichte der Änderungen zu verfolgen. Unter diesem Blickwinkel denken viele Leute bei einem Versionskontrollsystem an eine Art Zeitmaschine.

Subversion kann netzwerkübergreifend arbeiten, was die Benutzung durch Menschen an verschiedenen Computern ermöglicht. Auf einer bestimmten Ebene fördert die Fähigkeit unterschiedlicher Personen dieselbe Menge an Daten bearbeiten und verwalten zu können die Zusammenarbeit. Ohne auf einen einzigen Kanal, über den alle Änderungen abgewickelt werden müssen, beschränkt zu sein, kann das Vorankommen beschleunigt werden. Und weil die Arbeit versioniert ist, braucht nicht befürchtet zu werden, dass die Qualität bei Verlust dieses Kanals geopfert wird – falls irgendeine falsche Änderung an den Daten gemacht wird, kann man sie einfach zurücknehmen.

Manche Versionskontrollsysteme sind auch Software-Konfigurationsmanagement-Systeme. Diese Systeme sind maßgeschneidert, um ganze Verzeichnisbäume mit Quellcode zu verwalten und verfügen über viele Merkmale, die spezifisch für Software-Entwicklung sind – etwa das Verstehen von Programmiersprachen oder das Bereitstellen von Werkzeugen zum Bauen von Software. Jedoch gehört Subversion nicht zu diesen Systemen. Es ist ein allgemeines System, das verwendet werden kann, um alle möglichen Sammlungen von Dateien zu verwalten. Für Sie mag es sich dabei um Quellcode handeln – für andere mag es dabei um alles von Einkaufslisten bis zu digitalen Videomischungen und weit darüber hinaus gehen.

Ist Subversion das richtige Werkzeug?

Falls Sie ein Anwender oder Systemadministrator sind und den Einsatz von Subversion erwägen, sollte die erste Frage, die Sie sich stellen, sein: "Ist es das richtige Werkzeug für die Aufgabe?" Subversion ist ein fantastischer Hammer, achten Sie jedoch darauf, dass Sie nicht jedes Problem als einen Nagel sehen.

Falls Sie alte Datei- und Verzeichnisversionen aufbewahren, sie eventuell wiedererwecken müssen, oder Protokolle darüber auswerten möchten, wie sie sich im Lauf der Zeit geändert haben, ist Subversion das genau passende Werkzeug für Sie. Subversion ist auch geeignet, wenn Sie mit mehreren Leuten gemeinsam (üblicherweise über das Netz) an Dokumenten arbeiten und verfolgen müssen, wer welche Änderung gemacht hat. Deshalb wird Subversion so oft in Softwareentwicklungsumgebungen eingesetzt – die Arbeit in einem Entwicklerteam ist von Natur aus eine soziale Tätigkeit und Subversion vereinfacht die Zusammenarbeit mit anderen Programmierern. Natürlich ist die Benutzung von Subversion nicht umsonst zu bekommen: es kostet administrativen Aufwand. Sie müssen ein Daten-Repository verwalten, das die Informationen und ihre gesamte Geschichte speichert, und Sie müssen sich gewissenhaft um Sicherheitskopien kümmern. Wenn Sie täglich mit den Daten arbeiten, werden Sie sie nicht auf die gleiche Art kopieren, verschieben, umbenennen oder löschen können wie gewohnt. Stattdessen müssen Sie dafür Subversion verwenden.

Unter der Annahme, dass Ihnen die zusätzlichen Arbeitsabläufe nichts ausmachen, sollten Sie trotzdem sicher sein, dass Sie Subversion nicht für die Lösung eines Problems verwenden, das andere Werkzeuge besser lösen könnten. Zum Beispiel wird Subversion, weil es die Daten an alle Beteiligten verteilt, als generisches Verteilsystem missbraucht. Manchmal wird Subversion zum Verteilen von umfangreichen Bildersammlungen, digitaler Musik oder Softwarepaketen verwendet. Das Problem damit ist, dass sich diese Art Daten für gewöhnlich überhaupt nicht verändert. Die Sammlung selber wächst stetig, jedoch werden die einzelnen Dateien der Sammlung nicht verändert. In diesem Fall ist die Benutzung von Subversion zu viel des Guten.[2] Es gibt einfachere Werkzeuge, die hervorragend Daten replizieren, ohne dabei Änderungen mitzuverfolgen, etwa rsync oder unison.

Die Geschichte von Subversion

Anfang 2000 begann CollabNet, Inc. (http://www.collab.net) Entwickler zu suchen, die einen Ersatz für CVS schreiben sollten. CollabNet bietet eine Software-Suite namens CollabNet Enterprise Edition (CEE) für die Zusammenarbeit an, die auch eine Komponente für Versionskontrolle beinhaltet. Obwohl CEE ursprünglich CVS als Versionskontrollsystem verwendete, waren die Einschränkungen von CVS von Anfang an offensichtlich, und CollabNet war sich bewusst, dass letztendlich etwas Besseres gefunden werden musste. Unglücklicherweise war CVS der de-facto Standard in der Open-Source-Welt geworden, hauptsächlich deshalb, weil es nichts Besseres gab, zumindest nicht unter einer freien Lizenz. Also beschloss CollabNet, ein vollständig neues Versionskontrollsystem zu schreiben, welches die grundlegenden Ideen von CVS beibehalten, jedoch die Fehler und Fehlentwicklungen vermeiden sollte.

Im Februar 2000 nahmen sie Verbindung mit Karl Fogel auf, dem Autor von Open Source Development with CVS (Coriolis, 1999), und fragten ihn, ob er an diesem neuen Projekt mitarbeiten wolle. Zufälligerweise besprach Karl bereits einen Entwurf für ein neues Versionskontrollsystem mit seinem Freund Jim Blandy. Im Jahr 1995 gründeten die beiden Cyclic Software, eine CVS-Beratungsfirma, und sie benutzten, obwohl sie die Firma später verkauften, bei ihrer täglichen Arbeit immer noch CVS. Ihre Enttäuschung über CVS veranlasste Jim, sorgfältig über bessere Möglichkeiten zur Verwaltung versionierter Daten nachzudenken. Er hatte sich nicht nur bereits den Namen Subversion ausgedacht, sondern auch den grundsätzlichen Entwurf der Subversion-Datenablage. Als CollabNet rief, stimmte Karl sofort der Mitarbeit am Projekt zu, und Karl gelang es, dass sein Arbeitgeber Red Hat Software ihn praktisch auf unbestimmte Zeit dem Projekt spendete. CollabNet stellte Karl und Ben Collins-Sussman ein und der detaillierte Entwurfsprozess begann im Mai. Dank einiger Stupser von Brian Behrendorf und Jason Robbins von CollabNet sowie Greg Stein (zu dieser Zeit als unabhängiger Entwickler aktiv im der WebDAV/DeltaV Spezifikationsprozess), zog Subversion schnell eine Gemeinde aktiver Entwickler an. Es stellte sich heraus, dass viele Leute dieselben enttäuschenden Erfahrungen mit CVS gemacht hatten und nun die Gelegenheit begrüßten, etwas daran zu ändern.

Das ursprüngliche Designteam einigte sich auf einige einfache Ziele. Sie wollten kein Neuland in Versionskontrollmethodik betreten, sondern einfach CVS reparieren. Sie beschlossen, dass Subversion dieselben Merkmale und dasselbe Entwicklungsmodell wie CVS haben solle, wobei die Fehler von CVS aber nicht noch einmal gemacht werden sollten. Und obwohl es nicht als ein hundertprozentiger Ersatz für CVS gedacht war, sollte es dennoch ähnlich genug sein, so dass ein leichter Wechsel für einen CVS-Anwender möglich wäre.

Nach vierzehn Monaten Programmierung wurde Subversion am 31. August 2001 selbstbewirtend, d.h., die Subversion-Entwickler hörten auf, CVS für den Quellcode von Subversion zu verwenden und benutzten stattdessen Subversion.

Obwohl CollabNet das Projekt startete und immer noch einen großen Batzen der Arbeit finanziert (sie zahlen die Gehälter einiger Vollzeit-Subversion-Entwickler), läuft Subversion wie die meisten Open-Source-Projekte, geführt von einer Anzahl lockerer, transparenter Regeln, die die Meritokratie fördern. Die Urheberrechtslizenzen von CollabNet sind einvernehmlich mit den Debian Free Software Guidelines. Mit anderen Worten: Jeder darf Subversion nach Belieben herunterladen, ändern und weitergeben; es bedarf hierzu keinerlei Zustimmung durch CollabNet oder sonst jemanden.

Die Architektur von Subversion

Abbildung 1, „Die Architektur von Subversion“ illustriert einen kilometerhohen Blick auf das Design von Subversion.

Abbildung 1. Die Architektur von Subversion

Die Architektur von Subversion


An einem Ende ist das Repository von Subversion, das die gesamten versionierten Daten enthält. Am anderen Ende ist das Subversion-Client-Programm, das die lokale Spiegelung von Teilen dieser versionierten Daten verwaltet (Arbeitskopien genannt). Zwischen den entgegengesetzten Enden befinden sich mehrere Wege über verschiedene Repository-Zugriffsschichten. Einige dieser Pfade gehen über Computernetzwerke und über Netzwerkserver, die dann auf das Repository zugreifen. Andere lassen das Netz links liegen und greifen direkt auf das Repository zu.

Die Komponenten von Subversion

Sobald es installiert ist, hat Subversion eine Anzahl verschiedener Teile. Was folgt, ist ein schneller Überblick was Sie bekommen. Lassen Sie sich nicht beunruhigen, falls die kurzen Beschreibungen Sie dazu veranlassen, sich am Kopf zu kratzen – es gibt in diesem Buch jede Menge weiterer Seiten, die dem Ziel gewidmet sind, diese Verwirrung zu lindern.

svn

Das Kommandozeilenprogramm

svnversion

Ein Programm, das den Zustand einer Arbeitskopie (durch Revisionen der vorliegenden Objekte) berichtet

svnlook

Ein Werkzeug zur direkten Untersuchung eines Subversion-Repositorys

svnadmin

Ein Werkzeug zum Erstellen, Verändern oder Reparieren eines Repositorys

mod_dav_svn

Ein Plug-In-Modul für den Apache-HTTP-Server, wird benötigt, um das Repository über ein Netzwerk verfügbar zu machen

svnserve

Ein spezielles Server-Programm, dass als Hintergrundprozess laufen oder von SSH aufgerufen werden kann; eine weitere Möglichkeit, das Repository über ein Netzwerk verfügbar zu machen.

svndumpfilter

Ein Programm zum Filtern von Subversion-Repository-Dump-Streams

svnsync

Ein Programm zum inkrementellen Spiegeln eines Repositorys über ein Netzwerk

Was gibt es Neues in Subversion

Die erste Auflage dieses Buchs wurde 2004 herausgegeben, kurz nachdem Subversion die 1.0 erreicht hatte. Innerhalb der nächsten vier Jahre wurden fünf neue größere Versionen von Subversion freigegeben, die Fehler beseitigten und neue Features einführten. Während wir es schafften, die Online-Version dieses Buches aktuell zu halten, sind wir begeistert davon, dass die zweite Auflage von O'Reilly nun Subversion bis Release 1.5 behandelt, ein großer Meilenstein für das Projekt. Hier ist eine schnelle Zusammenfassung der größeren Änderungen seit Subversion 1.0. Beachten Sie, dass es keine komplette Liste ist; um alle Details zu sehen, besuchen Sie die Subversion-Website bei http://subversion.tigris.org.

Subversion 1.1 (September 2004)

Release 1.1 führte FSFS ein, eine Repository-Speicheroption, die auf Dateien basiert. Obwohl das Berkeley-DB-Backend immer noch weitverbreitet ist und unterstützt wird, ist FSFS mittlerweile wegen der niedrigen Einstiegshürde und des minimalen Wartungsbedarfs die Standard-Auswahl für neu erzeugte Repositorys. Ebenfalls kam mit diesem Release die Möglichkeit, symbolische Links unter Versionskontrolle zu stellen, das automatische Maskieren von URLs und eine sprachabhängige Benutzerschnittstelle.

Subversion 1.2 (Mai 2005)

Mit Release 1.2 konnten serverseitige Sperren auf Dateien erzeugt und somit der Commit-Zugriff für bestimmte Ressourcen serialisiert werden. Während Subversion immer noch grundsätzlich ein gleichzeitiges Versionskontrollsystem ist, können bestimmte Arten binärer Dateien (z.B. Kunstobjekte) nicht zusammengeführt werden. Die Sperrmöglichkeit stillt den Bedarf, solche Ressourcen zu versionieren und zu schützen. Zusammen mit dem Sperren kam auch eine vollständige WebDAV-Auto-Versionierungs-Implementierung, die es erlaubt, Subversion-Repositorys als Netzwerkverzeichnisse einzuhängen. Schließlich begann Subversion 1.2 einen neuen, schnelleren binären Differenzalgorithmus zu verwenden, um alte Versionen von Dateien zu komprimieren und hervorzuholen.

Subversion 1.3 (Dezember 2005)

Release 1.3 brachte pfadbasierte Autorisierungskontrolle für den svnserve-Server, was einem Merkmal entsprach, das vorher nur im Apache-Server vorzufinden war. Der Apache-Server wiederum bekam einige neue eigene Logging-Features, und die Subversion-API-Bindings für andere Sprachen machten auch große Sprünge vorwärts.

Subversion 1.4 (September 2006)

Release 1.4 führte ein völlig neues Werkzeug – svnsync – ein, um eine Einbahn-Replizierung von Repositorys über das Netz vornehmen zu können. Größere Teile der Arbeitskopie-Metadaten wurden überarbeitet, so dass nicht mehr XML benutzt wurde (was sich in erhöhter Geschwindigkeit auf Client-Seite niederschlug), während das Berkeley-DB-Repository-Backend die Fähigkeit erhielt, sich nach einem Server-Crash automatisch wiederherzustellen.

Subversion 1.5 (Juni 2008)

Release 1.5 brauchte viel länger als vorige Releases, doch das Hauptfeature war gigantisch: Halbautomatische Verfolgung des Verzweigens und Zusammenführens. Dies war eine riesige Wohltat für Anwender und schob Subversion weit jenseits der Fähigkeiten von CVS und in die Reihen kommerzieller Mitbewerber wie Perforce und ClearCase. Subversion 1.5 führte auch eine große Anzahl anderer, benutzerorientierter Features ein, wie die interaktive Auflösung von Dateikonflikten, partielle Checkouts, client-seitige Verwaltung von Änderungslisten, eine starke neue Syntax für External-Definitionen und SASL-Authentifizierungsunterstützung für den svnserve-Server.




[1] Oh, und Danke, Karl, dafür, dass du zu viel zu tun hattest, um das Buch selbst zu schreiben.

[2] Oder wie es ein Freund ausdrückt: Eine Fliege mit einem Buick erschlagen.

Kapitel 1. Grundlegende Konzepte

Das Kapitel ist eine kurze, lockere Einführung in Subversion. Wenn Sie noch nicht mit Versionskontrolle zu tun hatten, dann ist dieses Kapitel genau für Sie. Wir besprechen die grundlegenden Konzepte von Versionskontrolle und arbeiten uns in die Richtung von Subversion und dessen spezifischen Ideen und zeigen einfache Beispiele zur Anwendung.

Obwohl die Beispiele in diesem Kapitel Leute zeigen, die gemeinsam an Quellcode arbeiten, sei daran erinnert, dass Subversion alle möglichen Arten von Datensammlungen verwalten kann – es beschränkt sich nicht darauf, Entwicklern zu helfen.

Das Repository

Subversion ist ein zentralisiertes System zur gemeinsamen Nutzung von Informationen. In seinem Kern ist ein Repository ein zentraler Speicher von Daten. Das Repository speichert Informationen in Form eines Dateisystembaumes, typischerweise eine Hierarchie von Dateien und Verzeichnissen. Eine beliebige Anzahl von Clients verbinden sich mit dem Repository und lesen oder schreiben diese Dateien. Durch den Schreibvorgang, macht ein Client Informationen für andere verfügbar. Durch den Lesevorgang bekommt der Client Informationen von anderen zur Verfügung gestellt. Abbildung 1.1, „Ein typisches Client/Server System“ verdeutlicht das.

Abbildung 1.1. Ein typisches Client/Server System

Ein typisches Client/Server System


So, warum ist das interessant? Bis zu diesem Punkt hört sich das wie die Definition eines typischen File-Servers an. Und tatsächlich, das Repository ist eine Art von File-Server, aber nicht von der Art, die Sie kennen. Was das Subversion-Repository so speziell macht ist, dass es sich jede Änderung merkt, die jemals hineingeschrieben wurde. Jede Änderung an jeder Datei und auch Änderungen am Verzeichnisbaum selbst, wie z.B. das Hinzufügen, Löschen und Umstrukturieren von Dateien und Verzeichnissen.

Wenn ein Client Daten vom Repository liest, bekommt der Client üblicherweise nur die letzte Version des Dateisystem-Baumes zu sehen. Der Client hat aber auch die Möglichkeit, vorherige Zustände des Dateibaumes anzuschauen. Zum Beispiel kann ein Client somit die Frage stellen: Was beinhaltete das Verzeichnis am letzten Mittwoch? und Wer war die Person, die als letztes die Datei geändert hat und welche Änderungen hat sie gemacht?. Diese Art von Fragen sind die Grundlage eines Versionskontrollsystems, Systeme, die dazu entwickelt wurden, um die Änderungen an Daten über die Zeit hin aufzuzeichnen.

Versionierungsmodelle

Die zentrale Aufgabe eines Versionskontrollsystems ist es, die Zusammenarbeit beim Editieren gemeinsam benutzter Daten zu ermöglichen. Jedoch verwenden unterschiedliche Systeme auch unterschiedliche Strategien, um dies zu ermöglichen. Aus einer Reihe von Gründen ist es wichtig, diese Unterschiede zu verstehen. Erstmal hilft es dabei, bestehende Versionskontrollsysteme zu vergleichen und gegenüberzustellen, falls Ihnen andere Systeme begegnen, die Subversion ähneln. Darüber hinaus wird es Ihnen helfen, Subversion effektiver zu benutzen, da Subversion selbst eine Reihe unterschiedlicher Arbeitsweisen unterstützt.

Das Problem ??The Problem of File Sharing

Alle Versionskontrollsysteme haben alle die gleichen fundamentalen Probleme zu lösen: Wie soll es Anwendern erlaubt werden Informationen zu teilen aber Sie davor bewahren, sich gegenseitig auf die Fße zu treten? Es ist allzu einfach die Änderungen eines anderen im Repository zu überschreiben?

Stellen Sie sich einmal folgendes Abbildung 1.2, „The problem to avoid“Szenario vor: Zwei Kollegen, Harry und Sally, haben sich entschieden, die gleiche Datei zur gleichen Zeit zu bearbeiten. Harry speichert seine Änderungen zuerst im Repository, es ist aber möglich, dass Sally nur einige Augenblicke später mit ihrer Datei seine überschreibt. Harrys Änderungen der Datei sind zwar nicht für immer verloren (da das System jede Änderung aufzeichnet), aber alle seine Änderungen sind in Sallys später gespeicherter Version der Datei nicht vorhanden, da Sally diese Änderungen noch gar nicht kannte. Das heißt, dass Harrys Arbeit doch verloren ist, zumindest in der neuesten Version der Datei und das nur durch einen Zufall. Eine solche Situation wollen wir auf alle Fälle vermeiden.

Abbildung 1.2. The problem to avoid

The problem to avoid


The Lock-Modify-Unlock Solution

Viele Versionskontrollsysteme verwenden ein Sperren - Ändern - Entsperren-Modell um zu verhindern, dass verschiedene Autoren sich gegenseitig die Änderungen löschen. Bei diesem Modell erlaubt das Repository nur jeweils einem Programmierer den Zugriff auf eine Datei. Harry müsste also die Datei sperren, ehe er anfängt, seine Änderungen einzugeben. Wenn Harry die Datei gesperrt hat, kann Sally sie nicht ebenfalls sperren und daher auch nichts ändern. Sie kann die Datei in der Zeit nur lesen und darauf warten, dass Harry mit seiner Arbeit fertig ist und die Datei entsperrt. Abbildung 1.3, „Die Sperren - Ändern - Entsperren - Lösung veranschaulicht diese einfache Möglichkeit“

Abbildung 1.3. Die Sperren - Ändern - Entsperren - Lösung veranschaulicht diese einfache Möglichkeit

Die Sperren - Ändern - Entsperren - Lösung veranschaulicht diese einfache Möglichkeit


Das Problem bei einem Sperren - Ändern - Entsperren - Modell liegt in seinen Beschränkungen, die oft zu schier unüberwindlichen Hindernissen führen können.

  • Das Sperren kann zu administrativen Problemen führen. Vielleicht sperrt Harry eine Datei und vergisst dann, sie zu entsperren. In der Zwischenzeit sind Sally, die ebenfalls Änderungen an dieser Datei durchführen will, die Hände gebunden. Und dann geht Harry in Urlaub. Nun muss Sally sich an einen Administrator wenden, um die Datei entsperrt zu bekommen. Das Ergebnis sind unnötige Verzögerungen und vergeudete Zeit.

  • Das Sperren kann zu einer unnötigen Serialisierung führen. Was ist, wenn Harry z. B. den Anfang einer Textdatei bearbeiten will, während Sally einfach nur das Ende ändern möchte? Diese Änderungen würden sich überhaupt nicht gegenseitig beeinflussen und könnten problemlos gleichzeitig durchgeführt werden, vorausgesetzt, sie würden anschließend vernünftig zusammengefasst. Es gibt in dieser Situation keinen Grund, der Reihe nach zu arbeiten.

  • Das Sperren kann zu einem falschen Gefühl von Sicherheit führen. Angenommen Harry sperrt und bearbeitet Datei A, während Sally gleichzeitig Änderungen an Datei B durchführt. Was ist, wenn A und B voneinander abhängig sind und die jeweiligen Änderungen nicht kompatibel sind? Plötzlich funktioniert das Zusammenspiel zwischen A und B nicht mehr. Das System des Sperrens hat dieses Problem nicht verhindert, doch hat es fälschlicherweise zu einem Gefühl der Sicherheit geführt. Es ist leicht, sich vorzustellen, dass Harry und Sally der Meinung waren, dass jeder von ihnen eine eigenständige, voneinander unabhängige Änderung durchgeführt hat und dass das Sperren dazu geführt hat, dass sie ihre inkompatiblen Änderungen nicht vorher miteinander besprochen haben. Sperren ist oft ein Ersatz für echte Kommunikation.

Die „Kopieren – Ändern – Zusammenfassen“ - Lösung

Subversion, CVS und viele andere Versionskontrollsysteme benutzen eine „Kopieren – Ändern – Zusammenfassen“ — Version als Alternative zum Sperren. In diesem Modell erschafft jeder User sich eine eigene Arbeitskopie der im Repository vorhandenen Dateien und Verzeichnisse. Dann können die User gleichzeitig und unabhängig voneinander ihre jeweiligen Änderungen eingeben und speichern. Am Ende werden dann alle Einzelkopien zu einer neuen, aktuellen Version zusammengefasst. Das Versionskontrollsystem hilft oft bei dieser Zusammenfassung, aber letztlich ist der Mensch dafür verantwortlich, das es korrekt abläuft.

Hier ist ein Beispiel: Harry und Sally haben sich jeweils eine eigene Arbeitskopie des im Repository vorhandenen Projektes geschaffen. Beide arbeiten nun am selben File A innerhalb ihrer jeweiligen Kopien. Sally speichert ihre Version zuerst im Repository ab. Wenn Harry später ebenfalls versucht, seine Änderungen zu speichern, informiert ihn das Repository, das sein File A nicht mehr aktuell ist. Das bedeutet, dass seitdem er sich seine Kopie erschaffen hat, sind irgendwelche Änderungen aufgetreten. Also bittet Harry seinen Client darum, diese neuen Änderungen in seine Arbeitskopie des File A einzuarbeiten. Die Möglichkeit besteht, dass Sallys Änderungen mit seinen nicht überlappen, wenn er also alle Änderungen eingearbeitet hat, kann er seine Arbeitskopie zurück in das Repository speichern. Die Abbildungen Abbildung 1.4, „„Kopieren – Ändern – Zusammenfassen“ - Lösung“ und Abbildung 1.5, „„Kopieren – Ändern – Zusammenfassen“ - Lösung (Fortsetzung)“ zeigen diesen Proczess.

Abbildung 1.4. „Kopieren – Ändern – Zusammenfassen“ - Lösung

„Kopieren – Ändern – Zusammenfassen“ - Lösung


Abbildung 1.5. „Kopieren – Ändern – Zusammenfassen“ - Lösung (Fortsetzung)

„Kopieren – Ändern – Zusammenfassen“ - Lösung (Fortsetzung)


Was aber passiert, wenn Sallys Änderungen mit Harrys kollidieren? Diese Situation wird Konflikt genannt und ist normalerweise kein allzugroßes Problem. Wenn Harry Sallys Änderungen in seine Datei einpflegen lassen will, werden in seiner Datei die miteinander in Konflikt stehenden Änderungen gekennzeichnet, er kann sämtliche Änderungen sehen und manuell zwischen ihnen wählen. Das Programm löst solche Konfliktsituationen nicht automatisch, nur Menschen sind in der Lage, die Probleme zu erkennnen und die nötigen intelligenten Änderungen durchzuführen. Wenn Harry die Konfliktsituationen — vielleicht nach einer kurzen Diskussion mit Sally — gelöst hat, kann er seine Datei problemlos ins Repository speichern.

Dieses Kopieren – Ändern – Zusammenfassen - Modell (engl. copy-modify-merge model) klingt vielleicht ein wenig chaotisch, in der Praxis aber läuft es völlig glatt. Die einzelnen User können parallel arbeiten, ohne einander in die Quere zu kommen oder unnötig warten zu müsssen. Wenn sie an den selben Dateien arbeiten, zeigt es sich meistens, dass ihre jeweiligen Änderungen einander überhaupt nicht stören, wirkliche Konflikte sind selten. Und die Zeit, die es beansprucht, eine solche Konfliktsituation zu lösen, ist meist wesentlich kürzer als der Zeitverlust, der durch das Sperren auftritt.

Am Ende läuft alles auf einen kritischen Faktor hinaus. Die Kommunikation zwischen den Usern. Wenn diese Kommunikation eher spärlich abläuft, häufen sich sowohl semantische als auch syntaktische Konflikte. Kein System kann User dazu zwingen, vernünftig miteinander zu kommnunizieren und kein System kann semantische Konflikte erkennen. Also hat es auch keinen Sinn, sich in dem falschen Gefühl von Sicherheit zu wiegen, dass das Sperren Konflikte irgendwie vermeiden könnte. In der Praxis verringert das System des Sperrens mehr als andere die Produktivität.

Subversion in Action

Es ist an der Zeit, sich vom Abstrakten zum Konkreten zu bewegen. In diesem Abschnitt werden wir echte Beispiele zur Benutzung von Subversion zeigen.

Subversion-Repository-URLs

Das ganze Buch hindurch verwendet Subversion URLs, um Dateien und Verzeichnisse in Subversion-Repositorys zu identifizieren. Meistens benutzen diese URLs die Standardsyntax, die es erlaubt, Servernamen und Portnummern als Teil des URL zu spezifizieren:

$ svn checkout http://svn.example.com:9834/repos
…

Allerdings gibt es einige bemerkenswerte Feinheiten, wie Subversion mit URLs umgeht. Beispielsweise dürfen URLs, die die file://-Zugriffsmethode enthalten (für lokale Repositorys verwendet), gemäß Konvention entweder den Servernamen localhost oder gar keinen Servernamen enthalten:

$ svn checkout file:///var/svn/repos
…
$ svn checkout file://localhost/var/svn/repos
…

Darüber hinaus müssen Benutzer des file:// Schemas auf Windows-Plattformen eine inoffizielle Standard-Syntax verwenden falls auf Repositorys auf derselben Maschine aber auf einem anderen Laufwerk zugegriffen werden soll. Beide der folgenden URL-Pfad-Syntaxen funktionieren, wobei X das Laufwerk ist, wo das Repository liegt:

C:\> svn checkout file:///X:/var/svn/repos
…
C:\> svn checkout "file:///X|/var/svn/repos"
…

Bei der zweiten Syntax muss der URL in Anführungsstriche eingeschlossen werden, damit der senkrechte Strich nicht als Pipe-Symbol interpretiert wird. Beachten Sie auch, dass in einem URL Schrägstriche verwendet werden, obwohl es unter Windows üblich ist, für Pfade umgekehrte Schrägstriche zu verwenden.

[Anmerkung]Anmerkung

Sie können die file:// URLs von Subversion nicht in einem normalen Web-Browser auf die Art und Weise verwenden wie andere file:// URLs. Falls Sie versuchen, einen file:// URL in einem gewöhnlichen Web-Browser anzusehen, wird der Inhalt der Datei von der angegebenen Stelle direkt aus dem Dateisystem gelesen und angezeigt. Allerdings befinden sich die Daten von Subversion in einem virtuellen Dateisystem (siehe „Repository-Schicht“), und der Browser wird nicht mit diesem Dateisystem umzugehen wissen.

Zuletzt sei noch angemerkt, dass der Subversion-Client, wie ein Web-Browser, nötigenfalls automatisch URLs umwandelt. Falls zum Beispiel in einem URL Leerzeichen oder Großbuchstaben vorkommen wie hier:

$ svn checkout "http://host/path with space/project/españa"

wird Subversion die unsicheren Zeichen umwandeln, als ob Sie

$ svn checkout http://host/path%20with%20space/project/espa%C3%B1a

geschrieben hätten.

Falls ein URL Leerzeichen beinhalten sollte, stellen Sie sicher, das der URL in Anführungszeichen gesetzt wird, damit die Shell alles als ein Argument für das svn Programm behandelt.

Arbeitskopien

Sie haben schon über Arbeitskopien gelesen; nun werden wir zeigen, wie der Subversion-Client sie erzeugt und benutzt.

Eine Subversion-Arbeitskopie ist ein gewöhnlicher Verzeichnisbaum auf Ihrem lokalen System, der eine Ansammlung von Dateien enthält. Sie können diese Dateien nach belieben bearbeiten, und wenn es sich um Quelltexte handelt, können Sie hieraus Ihr Programm auf die übliche Weise compilieren. Ihre Arbeitskopie ist Ihr privater Arbeitsbereich: nie wird Subversion weder die Änderungen von anderen einpflegen, noch Ihre eigenen Änderungen anderen zur Verfügung stellen, bis Sie es ausdrücklich dazu auffordern. Sie können sogar mehrere Arbeitskopien desselben Projektes haben.

Nachdem Sie einige Änderungen an den Dateien Ihrer Arbeitskopie gemacht und sichergestellt haben, dass sie funktionieren, stellt Ihnen Subversion Befehle zur Verfügung, um Ihre Änderungen den anderen, die an Ihrem Projekt mitarbeiten, publik zu machen (indem es ins Repository schreibt). Wenn die anderen ihre Änderungen veröffentlichen, stellt Ihnen Subversion Befehle zur Verfügung, um diese Änderungen in Ihr Arbeitsverzeichnis einzupflegen (indem es aus dem Repository liest).

Eine Arbeitskopie verfügt darüber hinaus über einige zusätzliche Dateien, die von Subversion erzeugt und gepflegt werden, um es bei diesen Befehlen zu unterstützen. Insbesondere enthält jedes Verzeichnis Ihrer Arbeitskopie ein Unterverzeichnis namens .svn, auch bekannt als das Verwaltungsverzeichnis der Arbeitskopie. Die Dateien in jedem Verwaltungsverzeichnis helfen Subversion dabei, zu erkennen, welche Dateien unveröffentlichte Änderungen enthalten und welche Dateien hinsichtlich der Arbeit anderer veraltet sind.

Oft enthält ein typisches Subversion-Repository die Dateien (oder den Quelltext) für verschiedene Projekte; für gewöhnlich ist jedes Projekt ein Unterverzeichnis im Dateisystembaum des Repositorys. Bei dieser Anordnung entspricht die Arbeitskopie eines Benutzers gewöhnlich einem bestimmten Unterverzeichnis des Repositorys.

Nehmen wir zum Beispiel an, Sie haben ein Repository, das zwei Software-Projekte beinhaltet, paint und calc. Jedes Projekt ist in einem eigenen Hauptverzeichnis abgelegt, wie in Abbildung 1.6, „Das Dateisystem des Repositorys“ dargestellt.

Abbildung 1.6. Das Dateisystem des Repositorys

Das Dateisystem des Repositorys


Um eine Arbeitskopie zu erhalten, muss zunächst irgendein Teilbaum des Repositorys ausgecheckt werden(check out). (Der Begriff check out hört sich an, als habe es etwas mit dem Sperren oder Reservieren von Ressourcen zu tun, hat es aber nicht; es erzeugt lediglich eine private Kopie des Projektes für Sie.) Wenn Sie zum Beispiel /calc auschecken, bekommen Sie eine Arbeitskopie wie diese:

$ svn checkout http://svn.example.com/repos/calc
A    calc/Makefile
A    calc/integer.c
A    calc/button.c
Ausgecheckt, Revision 56.

$ ls -A calc
Makefile  button.c integer.c .svn/

Die Liste der As am linken Rand zeigt an, dass Subversion Ihrer Arbeitskopie eine Anzahl von Objekten hinzufügt (Add). Sie haben nun eine persönliche Kopie des Verzeichnisses /calc im Repository, mit einem zusätzlichen Eintrag – .svn – das, wie bereits erwähnt, die besonderen Informationen enthält, die Subversion benötigt.

Angenommen, Sie nehmen Änderungen an button.c vor. Da sich das Verzeichnis .svn den ursprünglichen Änderungszeitpunkt und den Inhalt der Datei merkt, kann Subversion erkennen, dass Sie die Datei verändert haben. Trotzdem veröffentlicht Subversion Ihre Änderungen solange nicht, bis Sie es ausdrücklich hierzu auffordern. Der Vorgang des Veröffentlichens von Änderungen über das Repository ist gemeinhin bekannter als commit (oder check in).

Um Ihre Änderungen anderen gegenüber zu veröffentlichen, können Sie den Subversion-Befehl svn commit verwenden:

$ svn commit button.c -m "Tippfehler in button.c korrigiert"
Sende          button.c
Übertrage Daten .
Revision 6 übertragen.

Nun sind Ihre Änderungen an button.c dem Repository überstellt, mitsamt einer Notiz, die Ihre Änderung beschreibt (nämlich, dass Sie einen Tippfehler beseitigt haben). Wenn eine andere Benutzerin eine Arbeitskopie von /calc auscheckt, wird sie Ihre Änderungen in der letzten Version der Datei sehen können.

angenommen, Sie haben eine Mitarbeiterin, Sally, die eine Arbeitskopie von /calc gleichzeitig mit Ihnen ausgecheckt hat. Wenn Sie Ihre Änderung an button.c committen, bleibt Sallys Arbeitskopie unverändert; Subversion ändert Arbeitskopien nur auf Wunsch des Benutzers.

Um ihr Projekt auf den neuesten Stand zu bringen, kann Sally Subversion dazu auffordern, ihre Arbeitskopie zu aktualisieren, indem sie den Befehl svn update verwendet. Das bringt sowohl Ihre als auch alle anderen Änderungen die committet wurden seit sie ausgecheckt hatte in ihre Arbeitskopie.

$ pwd
/home/sally/calc

$ ls -A
Makefile button.c integer.c .svn/

$ svn update
U    button.c
Aktualisiert zu Revision 57.

Die Ausgabe des svn update Befehls zeigt, dass Subversion den Inhalt von button.c aktualisiert hat (Update). Beachten Sie, dass Sally nicht angeben musste, welche Dateien zu aktualisieren sind; Subversion benutzt die Informationen aus dem .svn Verzeichnis und darüber hinaus weitere Informationen im Repository, um zu entscheiden, welche Dateien auf den neuesten Stand gebracht werden müssen.

Revisionen

Ein svn commit veröffentlicht Änderungen an einer beliebigen Anzahl von Dateien und Verzeichnissen als eine einzige atomare Transaktion. In Ihrer Arbeitskopie können Sie Dateiinhalte ändern, Dateien und Verzeichnisse erzeugen, löschen, umbenennen und kopieren und dann den gesamten Umfang der Änderungen als atomare Transaktion durch ein svn commit in das Repository einbringen.

Eine atomare Transaktion bedeutet: entweder es gehen alle Änderungen in das Repository oder keine. Angesichts von Programmabstürzen, Systemabstürzen, Netzproblemen oder anderer Benutzeraktionen hält Subversion an dieser Atomizität fest.

Jedes Mal wenn das Repository ein Commit annimmt, wird ein neuer Zustand des Dateisystem-Baums erzeugt, der Revision genannt wird. Jeder Revision wird eine einmalige natürliche Zahl zugewiesen, die um eins größer ist als die Vorgänger-Revision. Die anfängliche Revision eines frisch erzeugten Repositorys bekommt die Nummer 0 und besteht lediglich aus einem leeren Wurzelverzeichnis.

Abbildung 1.7, „Das Repository“ zeigt, wie man sich das Repository vorstellen kann. Stellen Sie sich eine Reihe von Revisionsnummern vor, die bei 0 startet und von links nach rechts wächst. Jede Revisionsnummer hat einen Dateisystem-Baum unter sich hängen, der ein Schnappschuss des Repositorys nach einem Commit ist.

Abbildung 1.7. Das Repository

Das Repository


Es ist wichtig zu beachten, dass eine Arbeitskopie nicht immer genau einer Revision im Repository zugeordnet werden kann; sie kann Dateien aus verschiedenen Revisionen beinhalten. Nehmen wir z.B. an, Sie checken sich eine Arbeitskopie einer Datei aus einem Repository aus, deren neueste Revision 4 ist:

calc/Makefile:4
     integer.c:4
     button.c:4

In diesem Augenblick entspricht Ihre Arbeitskopie exakt der Revision im Repository. Sie machen jetzt allerdings eine Änderung an button.c und bringen diese Änderung mit einem Commit ins Repository. Angenommen, dass keine weiteren Commits vorgenommen wurden, wird Ihr Commit die Revision 5 im Repository erzeugen, und Ihre Arbeitskopie sieht so aus:

calc/Makefile:4
     integer.c:4
     button.c:5

Angenommen, zu diesem Zeitpunkt macht Sally einen Commit für eine Änderung an integer.c und erzeugt Revision 6. Wenn Sie svn update verwenden, um Ihre Arbeitskopie zu aktualisieren, sieht sie so aus:

calc/Makefile:6
     integer.c:6
     button.c:6

Sallys Änderung an integer.c erscheint in Ihrer Arbeitskopie, und Ihre Änderung ist immer noch in button.c. In diesem Beispiel ist der Text von Makefile in den Revisionen 4, 5 und 6 identisch, jedoch markiert Subversion die Arbeitskopie von Makefile mit Revision 6, um zu zeigen, dass es noch aktuell ist. Wenn Sie also ein sauberes Update von der Wurzel Ihrer Arbeitskopie her machen, sollte sie im Allgemeinen genau einer Revision im Repository entsprechen.

Wie Arbeitskopien das Repository verfolgen

Für jede Datei eines Arbeitsverzeichnis merkt sich Subversion zwei essentielle Informationen im .svn/-Verwaltungsbereich:

  • Auf welcher Revision Ihre Arbeitsdatei aufbaut (das wird die Arbeitsrevision der Datei genannt)

  • Ein Zeitstempel, der festhält, wann die lokale Kopie das letzte Mal vom Repository aktualisiert wurde.

Mit diesen Informationen kann Subversion durch Kommunikation mit dem Repository feststellen, in welchem der folgenden Zustände sich eine Arbeitsdatei befindet:

Unverändert und aktuell

Die Datei im Arbeitsverzeichnis ist unverändert, und keinerlei Änderungen an der Datei sind seit der Arbeitsrevision an das Repository übergeben worden. Ein svn commit der Datei würde nichts machen, und ein svn update der Datei auch nicht.

Lokal geändert und aktuell

Die Datei wurde im Arbeitsverzeichnis geändert, und keinerlei Änderungen an der Datei sind seit der letzten Aktualisierung an das Repository übergeben worden. Es gibt lokale Änderungen, die noch nicht an das Repository übergeben worden sind, so dass ein svn commit der Datei Ihre Änderungen erfolgreich veröffentlichen würde, und ein svn update der Datei nichts tun würde.

Unverändert und veraltet

Die Datei wurde im Arbeitsverzeichnis nicht geändert, jedoch im Repository. Die Datei sollte aktualisiert werden, damit sie bezüglich der letzten öffentlichen Revision aktuell ist. Ein svn commit der Datei würde nichts machen, und ein svn update der Datei würde die letzten Änderungen in Ihre Arbeitskopie einbringen.

Lokal geändert und veraltet

Die Datei wurde sowohl im Arbeitsverzeichnis als auch im Repository geändert. Ein svn commit der Datei würde mit einem out-of-date Fehler abbrechen. Die Datei sollte erst aktualisiert werden; ein svn update Befehl würde versuchen, die öffentlichen mit den lokalen Änderungen zusammenzuführen. Wenn Subversion diese Zusammenführung nicht plausibel automatisch durchführen kann, wird die Auflösung des Konflikts dem Benutzer überlassen.

Das hört sich an, als müsse man jede Menge mitverfolgen, aber der svn status Befehl zeigt Ihnen den Zustand jedes Objektes in Ihrer Arbeitskopie. Weitergehende Informationen zu diesem Befehl finden Sie unter „Verschaffen Sie sich einen Überblick über Ihre Änderungen“.

Arbeitskopien mit gemischten Revisionen

Als allgemeingültiges Prinzip versucht Subversion, so flexibel wie möglich zu sein. Eine besondere Ausprägung der Flexibilität ist die Fähigkeit, eine Arbeitskopie bestehend aus Dateien und Verzeichnissen mit einer Mischung unterschiedlicher Revisionsnummern zu haben. Unglücklicherweise neigt diese Flexibilität dazu, eine Anzahl neuer Benutzer zu verwirren. Wenn Sie das vorangegangene Beispiel, das gemischte Revisionen vorgestellt hat, verwirrte, zeigen wir hier eine Einführung warum es diese Möglichkeit gibt und wie sie verwendet wird.

Updates und Commits sind getrennt

Eine der grundlegenden Regeln von Subversion ist, dass eine Aktion, die in das Repository schreibt keine Aktion zur Folge hat, die aus dem Repository liest und umgekehrt. Wenn Sie bereit sind, neue Änderungen an das Repository zu übergeben, heißt das noch lange nicht, dass Sie auch die Änderungen anderer haben möchten. Und wenn Sie noch an Änderungen arbeiten, sollte svn update elegant die Änderungen aus dem Repository mit Ihren Änderungen zusammenführen anstatt Sie dazu zu zwingen, Ihre Änderungen zu veröffentlichen.

Der hauptsächliche Nebeneffekt dieser Regel ist, dass eine Arbeitskopie zusätzlich buchhalten muss, um sowohl gemischte Revisionen zu verfolgen als auch diese Mischung vertragen zu können. Die Tatsache, dass auch Verzeichnisse selbst versioniert sind, verkompliziert die Sache nur.

Nehmen wir zum Beispiel an, Ihre Arbeitskopie besteht komplett aus Revision 10. Sie bearbeiten die Datei foo.html und führen ein svn commit aus, das die Revision 15 im Repository erzeugt. Nach dem erfolgreichen Commit würden viele neue Benutzer erwarten, dass die gesamte Arbeitskopie auf Revision 15 stehe, was aber nicht der Fall ist! Alle möglichen Änderungen können sich zwischen Revision 10 und 15 im Repository zugetragen haben. Der Client weiß nichts über diese Änderungen im Repository, da Sie noch nicht svn update aufgerufen haben, und svn commit zieht keine Änderungen herein. Wenn andererseits svn commit automatisch Änderungen hereinziehen würde, könnte die gesamte Arbeitskopie auf Revision 15 gebracht werden – doch dann wäre die grundlegende Regel verletzt, dass Lesen und Schreiben getrennte Aktionen sind. Deshalb ist das einzig Sichere, das der Subversion-Client tun kann, die eine Datei – foo.html – als zur Revision 15 gehörig zu kennzeichnen. Der Rest der Arbeitskopie verbleibt bei Revision 10. Nur durch svn update können die neuesten Änderungen hereingezogen und die gesamte Arbeitskopie als Revision 15 gekennzeichnet werden.

Gemischte Revisionen sind normal

Tatsache ist, dass jedes Mal wenn Sie svn commit aufgerufen haben, die Arbeitskopie aus irgendeiner Mischung von Revisionen besteht. Die Sachen, die Sie eben ins Repository gebracht haben, werden mit höheren Revisionsnummern gekennzeichnet als alles andere. Nach einigen Commits (ohne zwischenzeitliche Updates) ist Ihre Arbeitskopie eine Riesenmischung von Revisionen. Selbst wenn Sie die einzige Person sind, die das Repository benutzt, werden sie dieses Phänomen bemerken. Um Ihre Mischung aus Arbeitsrevisionen untersuchen zu können, verwenden Sie den Befehl svn status mit der --verbose-Option (siehe „Verschaffen Sie sich einen Überblick über Ihre Änderungen“ für weitergehende Informationen).

Oft ist neuen Benutzern überhaupt nicht bewusst, das ihre Arbeitskopie gemischte Revisionen beinhaltet. Das kann zur Verwirrung führen, weil viele Client-Programme empfindlich auf die Revision des Objektes reagieren, das sie untersuchen. Beispielsweise wird der svn log-Befehl verwendet, um die Historie der Änderungen einer Datei oder eines Verzeichnisses darzustellen (siehe „Erzeugung einer Liste der Änderungsgeschichte“). Wenn der Benutzer diesen Befehl auf ein Objekt in der Arbeitskopie anwendet, erwartet er, die gesamte Historie des Objektes zu sehen. Wenn jedoch die Arbeitsrevision des Objektes ziemlich alt ist (oftmals weil lange Zeit kein svn update aufgerufen wurde), wird die Historie der älteren Version des Objekts angezeigt.

Gemischte Revisionen sind nützlich

Wenn Ihr Projekt hinreichend komplex ist, werden Sie entdecken, dass es manchmal ganz nett sein kann, Teile Ihrer Arbeitskopie zurückzudatieren (oder auf eine ältere Version als die vorliegende zu aktualisieren); wie das gemacht wird, wird in Kapitel 2, Grundlegende Benutzung gezeigt. Vielleicht möchten Sie eine ältere Version eines Teilmoduls in einem Unterverzeichnis testen, oder Sie möchten herausbekommen, wann ein Fehler das erste Mal in einer Datei auftauchte. Dies ist der Zeitmaschinen-Aspekt eines Versionskontrollsystems – die Eigenschaft, die es ermöglicht, irgendeinen Teil Ihrer Arbeitskopie zeitlich nach vorne oder nach hinten zu verschieben.

Gemischte Revisionen haben ihre Grenzen

Wie auch immer Sie gemischte Revisionen in Ihrer Arbeitskopie verwenden, diese Flexibilität hat ihre Grenzen.

Erstens kann die Löschung einer Datei oder eines Verzeichnisses nicht an das Repository übergeben werden, wenn die Datei oder das Verzeichnis nicht ganz aktuell ist. Falls eine neuere Version im Repository existiert, wird Ihr Löschversuch abgelehnt, um zu vermeiden, dass Sie versehentlich Änderungen löschen, die Sie noch nicht gesehen haben.

Zweitens können Sie keine Änderungen an Metadaten eines Verzeichnisses an das Repository übergeben, wenn das Verzeichnis nicht ganz aktuell ist. In Kapitel 3, Advanced Topics werden Sie lernen, wie man Propertys an Objekte hängt. Die Arbeitskopie eines Verzeichnisses definiert eine bestimmte Menge von Einträgen und Propertys, so dass eine Property-Änderung an einem veralteten Verzeichnis Propertys zerstören kann, die Sie noch nicht gesehen haben.

Zusammenfassung

In diesem Kapitel haben wir eine Anzahl fundamentaler Konzepte von Subversion behandelt:

  • Wir haben die Begriffe zentrales Repository, Arbeitskopie und Reihe von Revisionsbäumen des Repositorys eingeführt.

  • Wir haben einige einfache Beispiele gesehen, wie zwei Mitarbeiter Subversion verwenden können, um gegenseitig Änderungen auszutauschen, indem das kopieren-verändern-zusammenführen-Modell benutzt wird.

  • Wir haben ein wenig darüber geredet, wie Subversion Informationen in einer Arbeitskopie verfolgt und verwaltet.

An dieser Stelle sollten Sie eine gute Vorstellung haben, wie Subversion ganz allgemein arbeitet. Mit diesem Kenntnisstand sollten Sie in der Lage sein, das nächste Kapitel anzugehen, das ein detaillierter Rundgang durch die Befehle und Eigenschaften von Subversion ist.

Kapitel 2. Grundlegende Benutzung

Nun kommen wir zu den Details der Benutzung von Subversion. Bis Sie das Ende dieses Kapitels erreicht haben, werden Sie in der Lage sein, alle Aufgaben zu erledigen, die sich bei der normalen täglichen Arbeit mit Subversion stellen. Sie werden damit beginnen, Ihre Dateien in Subversion einzupflegen, gefolgt von einem initialen Checkout Ihres Codes. Dann werden wir bei unserem Rundgang zeigen, wie Änderungen gemacht und diese Änderungen untersucht werden. Sie werden auch sehen, wie Sie die Änderungen anderer in Ihre Arbeitskopie bringen, untersuchen, und sich durch eventuell auftretende Konflikte arbeiten können.

Beachten Sie jedoch, dass dieses Kapitel nicht als erschöpfende Liste aller Befehle von Subversion gedacht ist – es ist eher eine Einführung in die gebräuchlichsten Aufgaben von Subversion, denen Sie begegnen werden. Dieses Kapitel setzt voraus, dass Sie Kapitel 1, Grundlegende Konzepte gelesen und verstanden haben und dass Sie mit dem allgemeinen Subversion-Modell vertraut sind. Für eine vollständige Referenz aller Befehle, siehe Kapitel 9, Die komplette Subversion Referenz.

Hilfe!

Bevor Sie weiter lesen: hier ist der wichtigste Befehl den Sie benötigen, wenn Sie Subversion verwenden: svn help. Der Subversion-Kommandozeilen-Client ist selbst-dokumentierend – jederzeit erklärt Ihnen ein schnelles svn help Unterbefehl die Syntax, die Optionen und das Verhalten des Unterbefehls.

$ svn help import
import: Überträgt eine nicht versionierte Datei oder einen Dateibaum in das
Projektarchiv.
Aufruf: import [PFAD] URL

  Überträgt rekursiv eine Kopie des PFADes zur URL.
  Ohne Angabe von PFAD wird ».« angenommen. Übergeordnete Verzeichnisse
  werden soweit erforderlich im Projektarchiv angelegt.
  Falls PFAD ein Verzeichnis ist, wird dessen Inhalt direkt unterhalb der URL
  hinzugefügt.
  Nicht versionierbare Elemente wie Gerätedateien und Pipes werden ignoriert,
  falls --force angegeben wird.

Gültige Optionen:
  -q [--quiet]             : nichts oder nur Zusammenfassungen ausgeben
  -N [--non-recursive]     : veraltet; versuchen Sie --depth=files oder
                             --depth=immediates
  --depth PAR              : begrenzt Operation durch Tiefe PAR (»empty«,
                            »files«, »immediates« oder »infinity«)
…

Wie Sie Daten in Ihr Repository bekommen

Sie können neue Dateien auf zweierlei Weisen in das Subversion-Repository bekommen: svn import und svn add. Wir werden svn import jetzt und svn add später in diesem Kapitel besprechen, wenn wir einen typischen Tag mit Subversion durchnehmen.

svn import

Mit dem svn import-Befehl kann ein unversionierter Verzeichnisbaum schnell in ein Repository kopiert werden, wobei benötigte Zwischenverzeichnisse nach Bedarf angelegt werden. svn import erfordert keine Arbeitskopie und pflegt Ihre Dateien sofort in das Repository ein. Typischerweise verwenden Sie diesen Befehl, wenn bereits ein Verzeichnisbaum besteht, den Sie aber in einem Subversion-Repository pflegen möchten. Zum Beispiel:

$ svnadmin create /var/svn/newrepos
$ svn import mytree file:///var/svn/newrepos/some/project \
             -m "Erstimport"
Hinzufügen     mytree/foo.c
Hinzufügen     mytree/bar.c
Hinzufügen     mytree/subdir
Hinzufügen     mytree/subdir/quux.h

Revision 1 übertragen.

Im vorstehenden Beispiel wurde der Inhalt des Verzeichnisses mytree unter dem Verzeichnis some/project im Repository abgelegt:

$ svn list file:///var/svn/newrepos/some/project
bar.c
foo.c
subdir/

Beachten Sie, dass nach dem Import der Originalbaum nicht in eine Arbeitskopie umgewandelt wird. Vor Beginn der Arbeit müssen Sie noch svn checkout ausführen, um eine frische Arbeitskopie des Baums zu erhalten.

Empfohlene Repository Aufteilung

Obwohl die Flexibilität von Subversion es Ihnen erlaubt, Ihr Repository nach Belieben aufzuteilen, empfehlen wir, ein Verzeichnis trunk für die Hauptlinie der Entwicklung, ein Verzeichnis branches für Branch-Kopien und ein Verzeichnis tags für Tag-Kopien. Zum Beispiel:

$ svn list file:///var/svn/repos
/trunk
/branches
/tags

In Kapitel 4, Verzweigen und Zusammenführen werden Sie mehr über Branches und Tags erfahren. Details über das Aufsetzen mehrerer Projekte finden Sie in „Aufbau des Repositorys“, und in „Planung der Organisation Ihres Repositorys“ lesen Sie mehr über Wurzelverzeichnisse von Projekten.

Anfänglicher Checkout

In den meisten Fällen werden Sie ein Subversion-Repository zu nutzen beginnen, indem Sie einen Checkout Ihres Projektes vornehmen. Das Auschecken eines Repositorys erzeugt eine Arbeitskopie desselben auf Ihrem lokalen Rechner. Diese Arbeitskopie umfasst die Revision HEAD (die letzte Revision) des auf der Kommandozeile angegebenen Subversion-Repositorys:

$ svn checkout http://svn.collab.net/repos/svn/trunk
A    trunk/Makefile.in
A    trunk/ac-helpers
A    trunk/ac-helpers/install.sh
A    trunk/ac-helpers/install-sh
A    trunk/build.conf
…
Ausgecheckt, Revision 8810.

Obwohl im vorangehenden Beispiel das Verzeichnis trunk ausgecheckt wird, können Sie genauso leicht irgendein tiefliegendes Unterverzeichnis aus einem Repository auschecken, indem Sie das Unterverzeichnis im URL beim Checkout angeben:

$ svn checkout \
      http://svn.collab.net/repos/svn/trunk/subversion/tests/cmdline/
A    cmdline/revert_tests.py
A    cmdline/diff_tests.py
A    cmdline/autoprop_tests.py
A    cmdline/xmltests
A    cmdline/xmltests/svn-test.sh
…
Ausgecheckt, Revision 8810.

Da Subversion ein copy-modify-merge-Modell (kopieren-ändern-zusammenführen) statt eines lock-modify-unlock-Modells (sperren-ändern-freigeben) verwendet (siehe „Versionierungsmodelle“), können Sie sofort damit beginnen, Änderungen an den Dateien und Verzeichnissen Ihrer Arbeitskopie vorzunehmen. Ihre Arbeitskopie ist wie jede beliebige andere Ansammlung aus Dateien und Verzeichnissen auf Ihrem System. Sie können sie bearbeiten, ändern, verschieben und sie sogar löschen und vergessen.

[Warnung]Warnung

Obwohl sich Ihre Arbeitskopie wie jede beliebige andere Ansammlung aus Dateien und Verzeichnissen auf Ihrem System verhält, können Sie zwar beliebig Dateien editieren, doch Sie müssen Subversion über alles andere was Sie tun in Kenntnis setzen. Wenn Sie z.B. ein Objekt in der Arbeitskopie kopieren oder verschieben möchten, sollten Sie svn copy oder svn move verwenden statt der Kopier- oder Verschiebebefehle Ihres Betriebssystems. Wir werden darauf später im Kapitel näher eingehen.

Sofern Sie nicht bereit sind, das Hinzufügen einer neuen Datei oder eines neuen Verzeichnisses oder Änderungen an bestehenden Objekten an das Repository zu übergeben, besteht keine Notwendigkeit, dem Subversion-Server mitzuteilen, dass Sie irgendetwas gemacht haben.

Obwohl Sie sicherlich eine Arbeitskopie mit dem Repository-URL als einziges Argument auschecken können, haben sie auch die Möglichkeit, ein Verzeichnis hinter dem Repository-URL anzugeben. Das erstellt Ihre Arbeitskopie in dem angegebenen Verzeichnis. Zum Beispiel:

$  svn checkout http://svn.collab.net/repos/svn/trunk subv
A    subv/Makefile.in
A    subv/ac-helpers
A    subv/ac-helpers/install.sh
A    subv/ac-helpers/install-sh
A    subv/build.conf
…
Ausgecheckt, Revision 8810.

Das legt Ihre Arbeitskopie in einem Verzeichnis namens subv ab anstatt in trunk so wie wir es früher schon einmal gemacht haben. Das Verzeichnis subv wird angelegt, sofern es nicht bereits vorhanden ist.

Das Zwischenspeichern des Passwortes abstellen

Wenn Sie eine Subversion-Operation ausführen, für die Sie sich authentifizieren müssen, speichert Subversion Ihre Zugangsdaten standardmäßig auf der Platte. Das geschieht zu Ihrer Annehmlichkeit, damit Sie bei künftigen Operationen nicht ständig Ihr Passwort eingeben müssen. Falls Sie wegen der Speicherung besorgt sein sollten, [3] können Sie das Zwischenspeichern entweder dauerhaft oder von Fall zu Fall abstellen.

Um das Passwort-Caching für einen bestimmten einmaligen Befehl zu unterbinden, übergeben Sie die --no-auth-cache-Option auf der Kommandozeile. Um das Caching dauerhaft abzustellen, können Sie der Subversion-Konfigurationsdatei Ihres lokalen Rechners die Zeile store-passwords = no hinzufügen. Für Details siehe „Client Credentials Caching“.

Authentifizierung als ein anderer Anwender

Da Subversion standardmäßig Zugangsdaten speichert (sowohl den Benutzernamen als auch das Passwort), erinnert es sich bequemerweise, wer Sie das letzte Mal waren, als Sie Ihre Arbeitskopie modifizierten. Doch manchmal ist das nicht hilfreich – besonders, wenn Sie in einer gemeinsam benutzten Arbeitskopie arbeiten wie in einem Konfigurationsverzeichnis oder im Dokumenten-Wurzelverzeichnis eines Webservers. In diesem Fall brauchen Sie nur die --username-Option auf der Kommandozeile zu übergeben und Subversion versucht, sich als dieser Benutzer zu authentifizieren und wird Sie, wenn nötig, zur Eingabe eines Passworts auffordern.

Der grundlegende Arbeitszyklus

Subversion hat zahlreiche Features, Optionen und noch jede Menge Schnickschnack, aber für die tägliche Arbeit ist die Wahrscheinlichkeit groß, nur wenig davon zu benutzen. In diesem Abschnitt gehen wir durch die gebräuchlichsten Dinge, die Sie während des Tagesgeschäftes mit Subversion machen werden.

Der typische Arbeitszyklus sieht so aus:

  1. Aktualisieren Sie Ihre Arbeitskopie.

    • svn update

  2. Nehmen Sie Änderungen vor.

    • svn add

    • svn delete

    • svn copy

    • svn move

  3. Untersuchen Sie Ihre Änderungen.

    • svn status

    • svn diff

  4. Nehmen Sie eventuell einige Änderungen zurück.

    • svn revert

  5. Lösen Sie Konflikte auf (arbeiten Sie die Änderungen anderer ein).

    • svn update

    • svn resolve

  6. Bringen Sie Ihre Änderungen ins Repository.

    • svn commit

Aktualisieren Sie Ihre Arbeitskopie

Wenn Sie in einem Projekt im Team zusammenarbeiten, sollten Sie Ihre Arbeitskopie aktualisieren, um die Änderungen zu bekommen, die die anderen Entwickler im Projekt seit Ihrer letzten Aktualisierung vorgenommen haben. Benutzen Sie svn update um Ihre Arbeitskopie synchron mit der letzten Revision im Repository zu bekommen:

$ svn update
U  foo.c
U  bar.c
Aktualisiert zu Revision 2.

In diesem Fall sieht es so aus, dass jemand Änderungen sowohl an foo.c als auch an bar.c übergeben hat, seit Sie das letzte Mal aktualisiert haben, und Subversion hat Ihre Arbeitskopie aktualisiert, damit sie beide Änderungen enthält.

Wenn der Server über svn update Änderungen an Ihre Arbeitskopie schickt, wird ein Buchstabencode neben jedem Objekt angezeigt, um Ihnen anzuzeigen, was Subversion gemacht hat, um die Arbeitskopie auf den neuesten Stand zu bringen. Zur Bedeutung der Buchstaben, rufen Sie svn help update auf.

Nehmen Sie Änderungen an Ihrer Arbeitskopie vor

Nun können Sie loslegen und Änderungen an Ihrer Arbeitskopie vornehmen. Normalerweise ist es am einfachsten, sich für eine bestimmte Änderung (oder eine Menge von Änderungen) zu entscheiden, etwa ein neues Feature zu implementieren oder einen Fehler zu beseitigen usw. Die Subversion-Befehle, die Sie hierfür verwenden werden sind svn add, svn delete, svn copy, svn move und svn mkdir. Falls Sie jedoch größtenteils Dateien editieren, die bereits mit Subversion verwaltet werden, brauchen Sie keinen dieser Befehle, bis Sie die Änderungen übergeben.

Sie können zwei Arten von Änderungen an Ihrer Arbeitskopie vornehmen: Dateiänderungen und Verzeichnisbaumänderungen. Sie brauchen Subversion nicht mitzuteilen, dass Sie beabsichtigen, eine Datei zu ändern; nehmen Sie einfach die Änderungen mit Ihrem Texteditor, Textverarbeitungsprogramm, Grafikprogramm oder sonstigen Programm vor, wie Sie es gewohnt sind. Subversion stellt automatisch fest, welche Dateien sich geändert haben und behandelt dabei Binärdateien genauso einfach wie Textdateien – und genauso effizient. Für Änderungen am Verzeichnisbaum können Sie Subversion mitteilen, Dateien und Verzeichnisse zum geplanten Entfernen, Hinzufügen, Kopieren oder Verschieben vorzumerken. Diese Änderungen finden sofort in Ihrer Arbeitskopie statt, doch nichts wird dem Repository hinzugefügt oder daraus entfernt, bevor Sie die Änderungen übergeben.

Hier ist ein Überblick der fünf Subversion-Unterbefehle, die Sie am häufigsten benutzen werden, um Änderungen am Verzeichnisbaum vorzunehmen:

svn add foo

Die Datei, das Verzeichnis oder den symbolischen Link foo zum Hinzufügen in das Repository vormerken. Wenn Sie das nächste Mal übergeben, wird foo ein Kind seines Elternverzeichnisses. Beachten Sie, dass alles unterhalb von foo zum Hinzufügen vorgemerkt wird, falls foo ein Verzeichnis ist. Falls Sie nur foo selber hinzufügen möchten, geben Sie die --depth empty-Option an.

svn delete foo

Die Datei, das Verzeichnis oder den symbolischen Link foo zum Löschen aus dem Repository vormerken. foo wird sofort aus der Arbeitskopie entfernt, falls es eine Datei oder ein Link ist. Falls foo ein Verzeichnis ist, wird es nicht gelöscht, sondern zum Löschen vorgemerkt. Wenn Sie Ihre Änderungen übergeben, wird das gesamte Verzeichnis foo aus der Arbeitskopie und dem Repository entfernt. [4]

svn copy foo bar

Erzeuge ein neues Objekt bar als Duplikat von foo und merke bar automatisch zum Hinzufügen vor. Wird bei der nächsten Übergabe bar dem Repository hinzugefügt, wird die Historie der Kopie mitaufgezeichnet (so wie sie ursprünglich in foo war). svn copy erzeugt keine Zwischenverzeichnisse, sofern nicht die Option --parents angegeben wird..

svn move foo bar

Dieser Befehl macht genau das gleiche wie svn copy foo bar; svn delete foo. D.h., bar wird zum Hinzufügen als Kopie von foo und foo selbst zum Löschen vorgemerkt. svn move erzeugt keine Zwischenverzeichnisse, sofern nicht die Option --parents angegeben wird.

svn mkdir blort

Dieser Befehl macht genau das gleiche wie mkdir blort; svn add blort. D.h., ein neues Verzeichnis namens blort wird angelegt und zum Hinzufügen vorgemerkt.

Untersuchen Sie Ihre Änderungen

Sobald Sie mit Ihren Änderungen fertig sind, müssen Sie sie ins Repository bringen; bevor Sie das jedoch machen, ist es normalerweise eine gute Idee, sich die Änderungen noch einmal anzusehen. Dadurch, dass Sie die Änderungen noch einmal begutachten, können Sie eine genauere Log-Nachricht schreiben. Sie könnten auch feststellen, dass Sie versehentlich eine Datei geändert haben, und hier haben Sie die Möglichkeit, vor der Übergabe die Änderung rückgängig zu machen. Zusätzlich bietet sich hierbei eine gute Gelegenheit, die Änderungen vor der Veröffentlichung noch einmal genau durchzugehen. Sie können sich mit svn status einen Überblick über Ihre Änderungen verschaffen und mit svn diff die Änderungen im Detail anzeigen lassen.

Subversion ist optimiert worden, um Ihnen bei dieser Aufgabe zu helfen, und es ist in der Lage, viele Dinge zu tun, ohne mit dem Repository kommunizieren zu müssen. Im Besonderen enthält Ihre Arbeitskopie eine versteckte unveränderte Kopie jeder versionskontrollierten Datei innerhalb des .svn-Bereichs. Deswegen kann Ihnen Subversion schnell zeigen, wie sich Ihre bearbeiteten Dateien geändert haben, und es erlaubt Ihnen sogar, Ihre Änderungen zurückzunehmen, ohne Verbindung mit dem Repository aufnehmen zu müssen.

Verschaffen Sie sich einen Überblick über Ihre Änderungen

Um einen Überblick über Ihre Änderungen zu bekommen, werden Sie den svn status-Befehl verwenden. Wahrscheinlich werden Sie den Befehl svn status häufiger benutzen als alle anderen Subversion-Befehle.

Wenn Sie svn status ganz oben in Ihrer Arbeitskopie aufrufen, werden alle Datei- und Verzeichnisbaumänderungen erfasst, die Sie gemacht haben. Hier sind einige Beispiele der häufigsten Statuscodes, die svn status zurückgeben kann. (Beachten Sie, dass der Text, der # folgt, nicht von svn status ausgegeben wird.)

?       scratch.c           # Datei ist nicht versionskontrolliert
A       stuff/loot/bloo.h   # Datei ist zum Hinzufügen vorgemerkt
C       stuff/loot/lump.c   # Datei hat Konflikte durch einen Update
D       stuff/fish.c        # Datei ist zum Löschen vorgemerkt
M       bar.c               # Der Inhalt von bar.c hat lokale Änderungen

In diesem Ausgabeformat zeigt svn status sechs Spalten mit Zeichen, gefolgt von mehreren Leerzeichen, gefolgt von einem Datei- oder Verzeichnisnamen an. Die erste Spalte gibt Aufschluss über den Zustand einer Datei oder eines Verzeichnisses und/oder des entsprechenden Inhalts.

A item

Die Datei, das Verzeichnis oder der symbolische Link item ist zum Hinzufügen in das Repository vorgemerkt.

C item

Die Datei item befindet sich in einem Konfliktzustand. D.h., Änderungen, die vom Server bei einer Aktualisierung empfangen wurden, überlappen sich mit lokalen Änderungen, die Sie in Ihrer Arbeitskopie haben (und konnten beim Aktualisieren nicht automatisch aufgelöst werden). Sie müssen den Konflikt auflösen, bevor Sie Ihre Änderungen in das Repository übergeben können.

D item

Die Datei, das Verzeichnis oder der symbolische Link item ist zum Löschen im Repository vorgemerkt.

M item

Der Inhalt der Datei item ist geändert worden.

Wenn Sie einen speziellen Pfad an svn status übergeben, bekommen Sie nur Informationen über das Objekt alleine:

$ svn status stuff/fish.c
D      stuff/fish.c

svn status hat auch eine --verbose-Option (-v), die Ihnen den Zustand jedes Objektes in der Arbeitskopie anzeigt, selbst wenn es sich nicht geändert hat:

$ svn status -v
M               44        23    sally     README
                44        30    sally     INSTALL
M               44        20    harry     bar.c
                44        18    ira       stuff
                44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
                44        21    sally     stuff/things
A                0         ?     ?        stuff/things/bloo.h
                44        36    harry     stuff/things/gloo.c

Dies ist das lange Format der Ausgabe von svn status. Die Buchstaben in der ersten Spalte bedeuten dasselbe wie vorher, jedoch zeigt die zweite Spalte die Arbeitsrevision des Objektes an. Die dritte und vierte Spalte zeigen die Revision der letzten Änderung an und wer es geändert hat.

Keiner der vorangegangenen Aufrufe von svn status stellt eine Verbindung zum Repository her – stattdessen werden die Metadaten im Verzeichnis .svn mit der Arbeitskopie verglichen. Schließlich gibt es die --show-updates-Option (-u), die eine Verbindung zum Repository herstellt, und Informationen darüber bereitstellt, was nicht mehr aktuell ist:

$ svn status -u -v
M      *        44        23    sally     README
M               44        20    harry     bar.c
       *        44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
A                0         ?     ?        stuff/things/bloo.h
Status bezogen auf Revision:   46

Beachten Sie die zwei Sternchen: Wenn Sie an dieser Stelle svn update aufrufen würden, erhielten Sie Änderungen an README und trout.c. Das gibt Ihnen einige sehr wichtige Informationen – Sie müssen aktualisieren, um die Änderungen auf dem Server an README mitzubekommen, bevor Sie übergeben, oder das Repository wird Ihre Übergabe ablehnen, da sie nicht aktuell ist (mehr dazu später).

svn status kann viel mehr Informationen über Dateien und Verzeichnisse in Ihrer Arbeitskopie anzeigen als wir hier gezeigt haben – für eine erschöpfende Beschreibung von svn status und dessen Ausgabe, siehe svn status.

Untersuchen Sie die Details Ihrer lokalen Änderungen

Eine andere Möglichkeit, Ihre Änderungen zu untersuchen, ist, den svn diff-Befehl zu verwenden. Sie können genau herausfinden, wie sie etwas geändert haben, indem Sie svn diff ohne Argumente aufrufen, das Ihnen Dateiänderungen im unified-diff-Format anzeigt:

$ svn diff
Index: bar.c
===================================================================
--- bar.c   (revision 3)
+++ bar.c   (working copy)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>

 int main(void) {
-  printf("Sixty-four slices of American Cheese...\n");
+  printf("Sixty-five slices of American Cheese...\n");
 return 0;
 }

Index: README
===================================================================
--- README  (revision 3)
+++ README  (working copy)
@@ -193,3 +193,4 @@
+Note to self:  pick up laundry.

Index: stuff/fish.c
===================================================================
--- stuff/fish.c    (revision 1)
+++ stuff/fish.c    (working copy)
-Welcome to the file known as 'fish'.
-Information on fish will be here soon.

Index: stuff/things/bloo.h
===================================================================
--- stuff/things/bloo.h (revision 8)
+++ stuff/things/bloo.h (working copy)
+Here is a new file to describe
+things about bloo.

Der svn diff-Befehl erzeugt diese Ausgabe, indem er Ihre Arbeitsdateien mit den unveränderten Kopien im Cache innerhalb des .svn-Bereichs vergleicht. Dateien, die zum Hinzufügen vorgemerkt sind, werden vollständig als hinzugefügter Text dargestellt, und Dateien, die zum Löschen vorgemerkt sind, werden vollständig als gelöschter Text dargestellt.

Die Ausgabe wird im unified-diff-Format dargestellt. D.h., gelöschte Zeilen werden mit einem vorangestellten - und hinzugefügte Zeilen mit einem vorangestellten + angezeigt. svn diff gibt auch Dateinamen und Offset-Informationen aus, die das patch-Programm verwenden kann, so dass Sie Patches erzeugen können, indem Sie die diff-Ausgabe in eine Datei umleiten:

$ svn diff > patchfile

Zum Beispiel können Sie die Patch-Datei vor einer Übergabe an einen anderen Entwickler zur Kontrolle oder zum Testen schicken.

Subversion verwendet seinen eingebauten diff-Algorithmus, der standardmäßig das unified-diff-Format benutzt. Falls Sie die Ausgabe von diff in einem anderen Format haben möchten, geben Sie ein externes diff-Programm mit der --diff-cmd-Option an, und übergeben Sie ihm beliebige Flags mit der --extensions-Option (-x). Um z.B. lokale Unterschiede in der Datei foo.c im Kontext-Ausgabeformat anzeigen zu lassen und dabei die Groß- und Kleinschreibung zu ignorieren, könnten Sie svn diff --diff-cmd /usr/bin/diff --extensions '-i' foo.c aufrufen.

Zurücknehmen von Änderungen in der Arbeitskopie

Angenommen, Sie stellen beim Ansehen der Ausgabe von svn diff fest, dass alle Änderungen, die Sie an einer bestimmten Datei gemacht haben, fehlerhaft waren. Vielleicht hätten Sie die Datei überhaupt nicht ändern sollen, oder es wäre einfacher, von Anfang an unterschiedliche Änderungen zu machen.

Dies ist die perfekte Gelegenheit, svn revert zu benutzen:

$ svn revert README
Rückgängig gemacht: »README«

Subversion stellt die Datei wieder so her, wie sie vor der Änderung war, indem sie mit der unveränderten Kopie aus dem Cache im .svn-Bereich überschrieben wird. Beachten Sie aber auch, dass svn revert jegliche vorgemerkten Operationen rückgängig machen kann – z.B. könnten Sie sich entscheiden, eine neue Datei erst gar nicht hinzufügen zu wollen:

$ svn status foo
?      foo

$ svn add foo
A         foo

$ svn revert foo
Rückgängig gemacht: »foo«

$ svn status foo
?      foo
[Anmerkung]Anmerkung

svn revert item hat genau denselben Effekt, wie item aus der Arbeitskopie zu löschen und dann svn update -r BASE item aufzurufen. Allerdings hat svn revert beim Rückgängigmachen einer Datei einen merklichen Unterschied – es muss beim Wiederherstellen der Datei nicht Verbindung mit dem Repository aufnehmen.

Oder vielleicht haben Sie die Datei versehentlich aus der Versionsverwaltung gelöscht:

$ svn status README

$ svn delete README
D         README

$ svn revert README
Rückgängig gemacht: »README«

$ svn status README

Konflikte auflösen (Änderungen anderer einarbeiten)

Wir haben bereits gesehen, wie svn status -u Konflikte vorhersagen kann. Angenommen, Sie starten svn update und einige interessante Dinge passieren:

$ svn update
U  INSTALL
G  README
Konflikt in »bar.c« entdeckt.
Auswahl: (p) zurückstellen, (df) voller Diff, (e) editieren,
        (h) Hilfe für weitere Optionen:

Die Codes U und G sind kein Grund zur Beunruhigung; diese Dateien haben die Änderungen aus dem Repository sauber aufgenommen. Die mit U markierten Dateien enthielten keine lokalen Änderungen, wurden jedoch mit Änderungen aus dem Repository geUpdatet. Das G steht für merGed, was bedeutet, dass die Datei zwar lokale Änderungen enthielt, die Änderungen aus dem Repository sich aber nicht damit überschnitten haben.

Die nächsten beiden Zeilen jedoch sind Teil eines Features (neu in Subversion 1.5) namens interaktive Konfliktauflösung. Das bedeutet, dass die Änderungen vom Server sich mit Ihren eigenen überschneiden, uns Sie nun die Gelegenheit haben, den Konflikt aufzulösen. Die gebräuchlichsten Optionen werden angezeigt, aber alle Optionen können sie sehen, wenn Sie h eintippen:

…
  (p)  zurückstellen      - den Konflikt erst später auflösen
  (df) voller Diff        - alle Änderungen in der zusammengeführten Datei anzeigen
  (e)  editieren          - zusammengeführte Datei in einem Editor ändern
  (r)  aufgelöst          - akzeptieren der zusammengeführten Version der Datei
  (mf) volle eigene Datei - die eigene Version der kompletten Datei akzeptieren
                            (ignorieren fremder Änderungen)
  (tf) volle fremde Datei - die fremde Version der kompletten Datei akzeptieren
                            (verlieren eigener Änderungen)
  (l)  starten            - Starten eines externen Programms zur Konfliktauflösung
  (h)  Hilfe              - diese Liste anzeigen

Bevor wir im Detail erklären, was jede Option bedeutet, gehen wir noch mal eben die Optionen durch.

(p)ostpone

Die Datei im Konfliktzustand lassen, um nach Abschluss der Aktualisierung die Konfliktauflösung durchzuführen.

(d)iff

Die Unterschiede zwischen der Basisrevision und der Konfliktdatei im unified-diff-Format anzeigen.

(e)dit

Die Konfliktdatei im bevorzugten Editor, wie in der Umgebungsvariablen EDITOR angegeben, öffnen.

(r)esolved

Nach dem Bearbeiten einer Datei teilen Sie svn mit, dass Sie die Konflikte in der Datei aufgelöst haben und der aktuelle Inhalt übernommen werden soll.

(m)ine-(f)ull

Die neuen vom Server erhaltenen Änderungen verwerfen und nur Ihre lokalen Änderungen an der zu überprüfenden Datei verwenden.

(t)heirs-(f)ull

Ihre lokalen Änderungen an der zu überprüfenden Datei verwerfen und nur die neuen vom Server erhaltenen Änderungen verwenden.

(l)aunch

Ein externes Programm zur Konfliktauflösung starten. Das setzt Vorbereitungen voraus.

(h)elp

Die Liste aller bei der interaktiven Konfliktauflösung möglichen Befehle anzeigen.

Wir werden diese Befehle nun detaillierter behandeln, wobei sie nach Funktionalität gruppiert werden.

Interaktive Begutachtung der Konflikte

Bevor Sie entscheiden, wie Sie einen Konflikt beseitigen wollen, wollen Sie wahrscheinlich genau sehen, worin der Konflikt besteht, und benutzen hierfür den Befehl diff (d):

…
Select: (p) postpone, (df) diff-full, (e) edit,
        (h)elp for more options : d
--- .svn/text-base/sandwich.txt.svn-base      Tue Dec 11 21:33:57 2007
+++ .svn/tmp/tempfile.32.tmp     Tue Dec 11 21:34:33 2007
@@ -1 +1,5 @@
-Just buy a sandwich.
+<<<<<<< .mine
+Go pick up a cheesesteak.
+=======
+Bring me a taco!
+>>>>>>> .r32
…

Die erste Zeile des diff-Inhalts zeigt den vorherigen Inhalt der Arbeitskopie (die BASE-Revision), die nächste Zeile beinhaltet Ihre Änderung und die letzte Zeile ist die Änderung, die soeben vom Server empfangen worden ist (gewöhnlich die HEAD-Revision). Mit diesen Informationen sind Sie bereit für den nächsten Schritt.

Interaktive Konfliktauflösung

Es gibt vier verschiedene Wege, um Konflikte interaktiv aufzulösen – von denen Ihnen zwei erlauben, Änderungen selektiv zusammenzuführen und zu editieren und zwei, die es Ihnen erlauben, einfach eine Version der Datei auszuwählen und weiterzumachen.

Falls Sie eine beliebige Kombination Ihrer lokalen Änderungen auswählen wollen, können Sie den edit-Befehl (e) verwenden, um die Datei mit den Konfliktmarken manuell in einem Texteditor (der durch die Umgebungsvariable EDITOR bestimmt wird) zu bearbeiten. Die Datei händisch in Ihrem Lieblingseditor zu bearbeiten ist eine Art Konflikte zu beseitigen, die sich einer ziemlich schlichten Technik bedient (siehe „Manuelle Konfliktauflösung“ für einen Beispieldurchgang), so dass manche Leute lieber feinste Zusammenführungs-Werkzeuge benutzen.

Um ein Zusammenführungs-Werkzeug benutzen zu können, müssen Sie entweder die Umgebungsvariable SVN_MERGE setzen oder die merge-tool-cmd-Option in Ihrer Subversion-Konfigurationsdatei definieren (siehe „Konfigurationsoptionen“ für weitere Details). Subversion übergibt vier Argumente an das Zusammenführungs-Werkzeug: die BASE-Revision der Datei, die Dateirevision, die durch die Aktualisierung vom Server empfangen wurde, die Dateirevision, die Ihre lokale Bearbeitung beinhaltet und die zusammengeführte Kopie der Datei (die Konfliktmarken enthält). Falls Ihr Zusammenführungs-Werkzeug die Argumente in einer anderen Reihenfolge oder in einem anderen Format erwartet, werden Sie ein Skript drumherum schreiben müssen, das von Subversion aufgerufen wird. Nachdem Sie die Datei bearbeitet haben und zufrieden mit Ihren Änderungen sind, können Sie Subversion mitteilen, dass für die bearbeitete Datei kein Konflikt mehr besteht, indem sie den resolve-Befehl (r) benutzen.

Falls Sie entscheiden, dass Sie keine Änderungen zusammenführen brauchen, sondern lediglich eine der beiden Dateiversionen akzeptieren wollen, können Sie entweder Ihre Änderungen (auch meine) mit dem mine-full-Befehl (mf) oder die der Anderen mit dem theirs-full-Befehl (tf) auswählen.

Aufschieben der Konfliktauflösung

Das hört sich vielleicht an wie ein passender Abschnitt zur Vermeidung von Ehestreitigkeiten, doch es geht immer noch um Subversion; also lesen Sie weiter. Falls Sie eine Aktualisierung vornehmen und ein Konflikt auftaucht, den Sie nicht begutachten oder auflösen können, ermöglicht Ihnen das Eingeben von p die Konfliktauflösung Datei für Datei aufzuschieben, wenn Sie svn update aufrufen. Falls Sie aktualisieren wollen, ohne Konflikte aufzulösen, können Sie die --non-interactive-Option an svn update übergeben, und jede Datei mit Konflikten wird automatisch mit einem C gekennzeichnet.

Das C bedeutet conflict. Das heißt, dass die Änderungen vom Server sich mit Ihren eigenen überschneiden, und Sie nach Abschluss der Aktualisierung manuell aus den Änderungen wählen müssen. Wenn Sie eine Konfliktauflösung verschieben, macht svn typischerweise drei Dinge, um Ihnen bei der Konfliktauflösung zu helfen:

  • Subversion gibt ein C während der Aktualisierung aus und merkt sich, dass die Datei in einem Konfliktzustand ist.

  • Falls Subversion die Datei als geeignet zum Zusammenführen ansieht, fügt es Konfliktmarken – besondere Zeichenketten, die die Konfliktregion begrenzen – in die Datei ein, um die überlappenden Bereiche besonders hervorzuheben. (Subversion verwendet das svn:mime-type-Property, um festzustellen, ob sich die Datei kontextuell zeilenweise zusammenführen lässt. Siehe „File Content Type“, um mehr zu erfahren.)

  • Für jede Datei mit Konflikten stellt Subversion drei zusätzliche unversionierte Dateien in Ihre Arbeitskopie:

    filename.mine

    Dies ist Ihre Datei aus der Arbeitskopie bevor Sie aktualisierten – d.h. ohne Konfliktmarken. Diese Datei beinhaltet nur Ihre letzten Änderungen. (Falls Subversion diese Datei als nicht-zusammenführbar erachtet, wird die .mine-Datei nicht erstellt, da sie identisch mit der Datei der Arbeitskopie wäre.)

    filename.rOLDREV

    Dies ist die Datei, die die BASE-Revision war bevor Sie Ihre Arbeitskopie aktualisiert haben; also die Datei, die Sie ausgecheckt hatten, bevor Sie Ihre letzten Änderungen machten.

    filename.rNEWREV

    Dies ist die Datei, die Ihr Subversion-Client soeben vom Server erhalten hat als Sie Ihre Arbeitskopie aktualisierten. Diese Datei entspricht der HEAD-Revision des Repositorys.

    Hierbei ist OLDREV die Revisionsnummer der Datei in Ihrem Verzeichnis .svn, und NEWREV ist die Revisionsnummer von HEAD im Repository.

Beispielsweise ändert Sally die Datei sandwich.txt aus dem Repository. Harry hat gerade diese Datei in seiner Arbeitskopie geändert und übergeben. Sally aktualisiert Ihre Arbeitskopie vor dem übergeben und bekommt einen Konflikt, den sie verschiebt:

$ svn update
Konflikt in »sandwich.txt« entdeckt.
Auswahl: (p) zurückstellen, (df) voller Diff, (e) editieren,
        (h) Hilfe für weitere Optionen: p
C  sandwich.txt
Aktualisiert zu Revision 2.
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2

An dieser Stelle erlaubt Subversion Sally nicht, die Datei sandwich.txt an das Repository zu übergeben, solange die drei temporären Dateien nicht entfernt werden:

$ svn commit -m "Add a few more things"
svn: Übertragen schlug fehl (Details folgen):
svn: Übertragung abgebrochen: »/home/sally/svn-work/sandwich.txt« bleibt im Konflikt

Falls Sie eine Konfliktauflösung aufgeschoben haben, müssen Sie den Konflikt auflösen, bevor Ihnen Subversion erlaubt, Ihre Änderungen in das Repository einzustellen. Sie werden dafür den svn resolve-Befehl mit einem von mehreren Argumenten für die --accept-Option aufrufen.

Falls Sie die Dateiversion vor Ihren Änderungen haben möchten, wählen Sie das base-Argument.

Falls Sie die Version möchten, die nur Ihre Änderungen enthält, wählen Sie das mine-full-Argument.

Falls Sie die Version möchten, die Ihre letzte Aktualisierung vom Server gezogen hat (und somit Ihre Änderungen vollständig verwerfen wollen), wählen Sie das Argument theirs-full.

Wenn Sie jedoch frei aus Ihren Änderungen und den Änderungen vom Server wählen möchten, führen Sie den konfliktbehafteten Text händisch zusammen (indem Sie die Konfliktmarken in der Datei begutachten und editieren) und wählen das working-Argument.

svn resolve entfernt die drei temporären Dateien und akzeptiert die Version, die Sie mit der --accept-Option angeben. Subversion betrachtet die Datei nun als nicht mehr konfliktbehaftet:

$ svn resolve --accept working sandwich.txt
Konflikt von »sandwich.txt« aufgelöst

Manuelle Konfliktauflösung

Das manuelle Auflösen von Konflikten kann ganz schön einschüchternd sein, wenn Sie es das erste Mal versuchen; jedoch kann es mit etwas Übung so leicht werden, wie vom Fahrrad zu fallen.

Hier ist ein Beispiel. Aufgrund einer schlechten Absprache bearbeiten Sie und Ihre Mitarbeiterin Sally gleichzeitig die Datei sandwich.txt. Sally übergibt ihre Änderungen an das Repository, und sobald Sie versuchen, Ihre Arbeitskopie zu aktualisieren, erhalten Sie einen Konflikt und müssen sandwich.txt bearbeiten, um den Konflikt aufzulösen. Zunächst wollen wir uns die Datei einmal ansehen:

$ cat sandwich.txt
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2
Creole Mustard
Bottom piece of bread

Die Zeichenketten aus Kleiner-als-Zeichen, Gleichheitszeichen und Größer-als-Zeichen sind Konfliktmarken und gehören nicht zu den eigentlichen Daten, die in Konflikt stehen. Im Allgemeinen werden Sie sicherstellen wollen, dass die Konflikte aus der Datei entfernt werden, bevor sie das nächste Mal eine Übergabe durchführen. Der Text zwischen den ersten beiden Marken besteht aus den Änderungen, die Sie im Konfliktbereich vorgenommen haben:

<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======

Der Text zwischen der zweiten und der dritten Marke ist der Text aus Sallys Übergabe:

=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2

Für gewöhnlich werden Sie nicht einfach die Konfliktmarken mitsamt der Änderungen von Sally löschen wollen – sie wird furchtbar überrascht sein, wenn das Sandwich kommt und nicht das drauf ist, was sie wollte. Hier ist der Zeitpunkt gekommen, zu dem Sie zum Telefon greifen oder durch das Büro gehen und Sally erklären, dass man in einem italienischen Delikatessenladen kein Sauerkraut bekommt. [6] Sobald Sie sich über die zu übergebenden\ Änderungen einig sind, können Sie Ihre Datei bearbeiten und die Konfliktmarken entfernen:

Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
Salami
Mortadella
Prosciutto
Creole Mustard
Bottom piece of bread

Verwenden Sie jetzt svn resolve, und Sie sind bereit, Ihre Änderungen an das Repository zu übergeben:

$ svn resolve --accept working sandwich.txt
Konflikt von »sandwich.txt« aufgelöst
$ svn commit -m "Mach weiter mit meinem Sandwich, vergiss Sallys Änderungen."

Beachten Sie, dass svn resolve, anders als die meisten anderen Befehle, die wir in diesem Kapitel behandeln, erwartet, dass Sie ausdrücklich alle Dateien aufzählen, deren Konflikt Sie beseitigt haben. Auf alle Fälle sollten Sie sorgfältig vorgehen und svn resolve nur verwenden, falls Sie sicher sind, den Konflikt in Ihrer Datei beseitigt zu haben – sobald die temporären Dateien entfernt sind, lässt Subversion zu, dass Sie die Datei in das Repository stellen, selbst wenn sie noch Konfliktmarken enthält.

Falls Sie mal bei der Bearbeitung der konfliktbehafteten Datei verwirrt sein sollten, können Sie jederzeit in den drei Dateien nachsehen, die Subversion für Sie in der Arbeitskopie bereitstellt – dazu gehört auch Ihre Datei vor der Aktualisierung. Sie können sogar ein Zusammenführungs-Werkzeug eines Drittanbieters verwenden, um diese drei Dateien zu untersuchen.

Verwerfen Ihrer Änderungen zugunsten einer aktualisierten Revision aus dem Repository

Falls Sie einen Konflikt erhalten und entscheiden, dass Sie Ihre Änderungen verwerfen wollen, können Sie svn resolve --accept theirs-full CONFLICTED-PATH aufrufen, und Subversion wird Ihre Änderungen ignorieren und die temporären Dateien entfernen:

$ svn update
Konflikt in »sandwich.txt« entdeckt.
Auswahl: (p) zurückstellen, (df) voller Diff, (e) editieren,
        (h) Hilfe für weitere Optionen: p
C    sandwich.txt
Aktualisiert zu Revision 2.
$ ls sandwich.*
sandwich.txt  sandwich.txt.mine  sandwich.txt.r2  sandwich.txt.r1
$ svn resolve --accept theirs-full sandwich.txt
Konflikt von »sandwich.txt« aufgelöst

Die Verwendung von svn revert

Falls Sie sich entscheiden, Ihre Änderungen zu verwerfen und erneut mit der Bearbeitung zu beginnen (ob nach einem Konflikt oder sonst zu jeder Zeit), machen Sie einfach Ihre Änderungen rückgängig:

$ svn revert sandwich.txt
Rückgängig gemacht: »sandwich.txt«
$ ls sandwich.*
sandwich.txt

Beachten Sie, dass Sie beim Rückgängigmachen einer konfliktbehafteten Datei nicht svn resolve zu verwenden brauchen.

Übergeben Ihrer Änderungen

Endlich! Sie haben die Bearbeitung abgeschlossen, Sie haben alle Änderungen vom Server eingearbeitet, und Sie sind bereit, Ihre Änderungen an das Repository zu übergeben.

Der Befehl svn commit schickt all Ihre Änderungen zum Repository. Wenn Sie eine Änderung übergeben, müssen Sie einen Protokolleintrag erstellen, der die Änderung beschreibt. Dieser Eintrag wird mit der von Ihnen erzeugten neuen Revision verknüpft. Wenn Ihr Eintrag kurz ist, können Sie ihn mit der Option --message (oder -m) in der Kommandozeile angeben:

$ svn commit -m "Anzahl Käsescheiben korrigiert."
Sende          sandwich.txt
Übertrage Daten .
Revision 3 übertragen.

Falls Sie jedoch Ihren Protokolleintrag während der Arbeit erstellen möchten, können Sie Subversion mitteilen, sich den Eintrag aus einer Datei zu holen, indem Sie den Dateinamen mit der Option --file (-F) angeben:

$ svn commit -F logmsg
Sende          sandwich.txt
Übertrage Daten .
Revision 4 übertragen.

Sollten Sie vergessen, entweder die Option --message oder die --file-Option anzugeben, startet Subversion automatisch Ihren Lieblingseditor (siehe die Information zu editor-cmd in „Config“), damit Sie einen Protokolleintrag erstellen können.

[Tipp]Tipp

Wenn Sie gerade in Ihrem Editor einen Eintrag schreiben und sich entschließen, die Übergabe abzubrechen, können Sie einfach Ihren Editor beenden, ohne die Änderungen zu sichern. Falls Sie den Eintrag bereits gesichert haben sollten, löschen Sie einfach den Text, sichern Sie erneut und brechen dann ab:

$ svn commit

Logmeldung unverändert oder nicht angegeben
A)bbrechen, Weitermac)hen, E)ditieren:
a
$

Das Repository weiß nicht, ob Ihre Änderung im Ganzen einen Sinn ergeben, es ist ihm auch egal; es überprüft lediglich, ob nicht irgendjemand anderes irgendeine derselben Dateien geändert hat wie Sie, als Sie mal weggeschaut haben. Falls jemand das gemacht hat, wird die gesamte Übergabe mit einer Meldung fehlschlagen, dass eine oder mehrere Ihrer Dateien nicht mehr aktuell sind:

$ svn commit -m "Noch eine Regel hinzufügen"
Sende          rules.txt
svn: Übertragen schlug fehl (Details folgen):
svn: Datei »/rules.txt« ist veraltet
…

(Der genaue Wortlaut dieser Fehlermeldung hängt vom verwendeten Netzwerkprotokoll und vom Server ab, doch die Bedeutung ist in allen Fällen gleich.)

Zu diesem Zeitpunkt müssen Sie svn update aufrufen, sich um eventuelle Zusammenführungen oder Konflikte kümmern und die Übergabe erneut versuchen.

Das deckt den grundlegenden Arbeitszyklus für die Verwendung von Subversion ab. Subversion bietet viele andere Möglichkeiten, die Sie benutzen können, um Ihr Repository und Ihre Arbeitskopie zu verwalten, doch der größte Teil Ihrer täglichen Arbeit mit Subversion wird lediglich die in diesem Kapitel behandelten Befehle berühren. Wir werden jedoch noch ein paar mehr Befehle behandeln, die Sie ziemlich oft verwenden werden.

Geschichtsforschung

Ihr Subversion-Repository ist wie eine Zeitmaschine. Es legt einen Eintrag für jede jemals übergebene Änderung an und erlaubt Ihnen, diese Geschichte durch die Untersuchung sowohl ehemaliger Datei- und Verzeichnisversionen als auch der begleitenden Metadaten zu erforschen. Mit einem einzigen Subversion-Befehl können Sie das Repository genauso auschecken (oder eine bestehende Arbeitskopie wiederherstellen), wie es zu einem beliebigen Zeitpunkt oder einer Revisionsnummer in der Vergangenheit war. Allerdings möchten Sie manchmal nur in die Vergangenheit spähen anstatt dorthin zu gehen.

Es gibt mehrere Befehle, die Sie mit historischen Daten aus dem Repository versorgen können:

svn log

Zeigt Ihnen grobe Informationen: Mit Revisionen verknüpfte Protokolleinträge zu Datum und Autor und welche Pfade sich in jeder Revision geändert haben.

svn diff

Zeigt die Details einer bestimmten Änderung auf Zeilenebene

svn cat

Holt eine Datei hervor wie sie mit einer bestimmten Revisionsnummer einmal ausgesehen hat und zeigt sie auf dem Bildschirm an

svn list

Zeigt die Dateien in einem Verzeichnis für eine gewünschte Revision an

Erzeugung einer Liste der Änderungsgeschichte

Um Informationen über den Werdegang einer Datei oder eines Verzeichnisses zu bekommen, benutzen Sie den Befehl svn log. svn log versorgt Sie mit einem Eintrag, der Auskunft darüber gibt, wer Änderungen an einer Datei oder einem Verzeichnis gemacht hat, in welcher Revision die Änderung stattfand, zu welcher Zeit und welchem Datum die Revision entstand sowie – falls verfügbar – dem die Übergabe begleitenden Protokolleintrag:

$ svn log
------------------------------------------------------------------------
r3 | sally | 2008-05-15 23:09:28 -0500 (Thu, 15 May 2008) | 1 line

include-Zeilen hinzugefügt und Anzahl der Käsescheiben korrigiert.
------------------------------------------------------------------------
r2 | harry | 2008-05-14 18:43:15 -0500 (Wed, 14 May 2008) | 1 line

main()-Methoden hinzugefügt.
------------------------------------------------------------------------
r1 | sally | 2008-05-10 19:50:31 -0500 (Sat, 10 May 2008) | 1 line

Erstimport
------------------------------------------------------------------------

Beachten Sie, dass die Protokolleinträge standardmäßig in umgekehrter zeitlicher Reihenfolge ausgegeben werden. Falls Sie eine andere Folge von Revisionen in einer bestimmten Anordnung oder nur eine einzige Revision sehen möchten, übergeben Sie die Option --revision (-r):

$ svn log -r 5:19    # zeigt Protokolleintrag 5 bis 19 in chronologischer Reihenfolge

$ svn log -r 19:5    # zeigt Protokolleintrag 5 bis 19 in umgekehrter Reihenfolge

$ svn log -r 8       # zeigt Protokolleintrag für Revision 8

Sie können sich auch die Protokollgeschichte einer einzigen Datei oder eines einzigen Verzeichnisses ansehen. Zum Beispiel:

$ svn log foo.c
…
$ svn log http://foo.com/svn/trunk/code/foo.c
…

Diese Befehle zeigen nur Protokolleinträge für die Revisionen, in der sich die Arbeitsdatei (oder URL) geändert hat.

Wenn Sie noch mehr Informationen über eine Datei oder ein Verzeichnis benötigen, können Sie svn log auch die Option --verbose (-v) mitgeben. Weil Ihnen Subversion erlaubt, Dateien und Verzeichnisse zu kopieren und zu verschieben, ist es wichtig, Pfadänderungen im Dateisystem mitzuverfolgen. Daher beinhaltet bei dieser Option die Ausgabe von svn log eine Liste veränderter Pfade in einer Revision:

$ svn log -r 8 -v
------------------------------------------------------------------------
r8 | sally | 2008-05-21 13:19:25 -0500 (Wed, 21 May 2008) | 1 line
Geänderte Pfade:
   M /trunk/code/foo.c
   M /trunk/code/bar.h
   A /trunk/code/doc/README

Die Unterraumwinde gefrozzelt.

------------------------------------------------------------------------

svn log akzeptiert ebenfalls die Option --quiet (-q), die den Protokolleintrag unterdrückt. Zusammen mit der Option --verbose zeigt es nur die Namen der geänderten Dateien an.

Detaillierte Untersuchung der Änderungsgeschichte

svn diff ist uns bereits begegnet – es zeigt Dateiunterschiede im unified-diff-Format; wir verwendeten es, um die lokalen Änderungen an unserer Arbeitskopie anzuzeigen, bevor wir sie dem Repository übergaben.

Tatsächlich stellt sich heraus, dass es drei verschiedene Verwendungsmöglichkeiten für svn diff gibt:

  • zum Untersuchen lokaler Änderungen

  • zum Vergleichen Ihrer Arbeitskopie mit dem Repository

  • zum Vergleichen von Revisionen im Repository

Untersuchen lokaler Änderungen

Wie wir gesehen haben, vergleicht der Aufruf von svn diff ohne Optionen die Arbeitsdateien mit den zwischengespeicherten ursprünglichen Kopien im .svn-Bereich:

$ svn diff
Index: rules.txt
===================================================================
--- rules.txt   (revision 3)
+++ rules.txt   (working copy)
@@ -1,4 +1,5 @@
 Be kind to others
 Freedom = Responsibility
 Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$

Vergleichen der Arbeitskopie mit dem Repository

Wird eine einzelne Nummer mit --revision (-r) übergeben, wird die Arbeitskopie mit der angegebenen Revision im Repository verglichen:

$ svn diff -r 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt   (revision 3)
+++ rules.txt   (working copy)
@@ -1,4 +1,5 @@
 Be kind to others
 Freedom = Responsibility
 Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$

Vergleichen von Repository mit Repository

Werden zwei Revisionsnummern durch einen Doppelpunkt getrennt mit --revision (-r) übergeben, werden die beiden Revisionen direkt miteinander verglichen:

$ svn diff -r 2:3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt   (revision 2)
+++ rules.txt   (revision 3)
@@ -1,4 +1,4 @@
 Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
 Everything in moderation
 Chew with your mouth open
$

Eine bequemere Möglichkeit, eine Revision mit der Vorgänger-Revision zu vergleichen, bietet die Verwendung der Option --change (-c):

$ svn diff -c 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt   (revision 2)
+++ rules.txt   (revision 3)
@@ -1,4 +1,4 @@
 Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
 Everything in moderation
 Chew with your mouth open
$

Zu guter Letzt können Sie Revisionen im Repository auch dann vergleichen, falls Sie gar keine Arbeitskopie auf Ihrem lokalen Rechner haben, indem Sie einfach den entsprechenden URL auf der Kommandozeile angeben:

$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt
…
$

Stöbern im Repository

Wenn Sie svn cat und svn list verwenden, können Sie sich verschiedene Revisionen von Dateien und Verzeichnissen ansehen, ohne die Revision Ihrer Arbeitskopie ändern zu müssen. Tatsächlich brauchen Sie dafür nicht einmal eine Arbeitskopie.

svn cat

Falls Sie eine frühere Version einer Datei untersuchen möchten und nicht notwendigerweise die Unterschiede zwischen zwei Dateien, können Sie svn cat verwenden:

$ svn cat -r 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
Everything in moderation
Chew with your mouth open
$

Sie können die Ausgabe auch direkt in eine Datei umleiten:

$ svn cat -r 2 rules.txt > rules.txt.v2
$

svn list

Der Befehl svn list zeigt Ihnen, welche Dateien sich in einem Repository-Verzeichnis befinden, ohne die Dateien auf Ihren lokalen Rechner herunterladen zu müssen:

$ svn list http://svn.collab.net/repos/svn
README
branches/
clients/
tags/
trunk/

Falls Sie eine detailliertere Auflistung wünschen, übergeben Sie die Option --verbose (-v), um eine Ausgabe ähnlich der folgenden zu bekommen:

$ svn list -v http://svn.collab.net/repos/svn
  20620 harry            1084 Jul 13  2006 README
  23339 harry                 Feb 04 01:40 branches/
  21282 sally                 Aug 27 09:41 developer-resources/
  23198 harry                 Jan 23 17:17 tags/
  23351 sally                 Feb 05 13:26 trunk/

Die Spalten zeigen Ihnen die Revision, in der die Datei zuletzt geändert wurde, den Benutzer, der sie änderte, die Größe, falls es sich um eine Datei handelt, sowie den Namen des Objektes.

[Warnung]Warnung

Der Befehl svn list ohne Argumente verwendet standardmäßig den Repository-URL des aktuellen Arbeitsverzeichnisses und nicht das Verzeichnis der lokalen Arbeitskopie. Schließlich können Sie, falls Sie eine Auflistung des lokalen Verzeichnisses möchten, das einfache ls (oder irgendein vernünftiges nicht-unixartiges Äquivalent) benutzen.

Bereitstellung älterer Repository-Schnappschüsse

Zusätzlich zu den obigen Befehlen können Sie svn update und svn checkout mit der Option --revision verwenden, um eine vollständige Arbeitskopie zeitlich zurückzusetzen: [7]

$ svn checkout -r 1729 # Checkt eine neue Arbeitskopie von r1729 aus
…
$ svn update -r 1729 # Aktualisiert eine bestehende Arbeitskopie auf r1729
…
[Tipp]Tipp

Viele Subversion-Neulinge versuchen das vorangehende svn update-Beispiel zu verwenden, um übergebene Änderungen rückgängig zu machen, was allerdings nicht funktioniert, da Sie keine Änderungen übergeben können, die Sie durch das zeitliche Zurücksetzen einer Arbeitskopie erhalten haben, falls die geänderten Dateien neuere Revisionen haben. Siehe „Zurückholen gelöschter Objekte“ für eine Beschreibung, wie eine Übergabe rückgängig gemacht wird.

Wenn Sie am Ende ein Release bauen und die Dateien aus Subversion zu einem Bündel schnüren möchten, ohne allerdings diese verdammten .svn-Verzeichnisse dabei zu haben, können Sie svn export verwenden, um eine lokale Kopie des gesamten oder teilweisen Repositorys ohne .svn-Verzeichnisse zu erhalten. Wie bei svn update und svn checkout können Sie auch hier die Option --revision an svn export übergeben:

$ svn export http://svn.example.com/svn/repos1 # Exportiert die letzte Revision
…
$ svn export http://svn.example.com/svn/repos1 -r 1729
# Exportiert Revision r1729
…

Manchmal müssen Sie einfach nur aufräumen

Nachdem wir nun die täglichen Aufgaben abgehandelt haben, für die Sie regelmäßig Subversion verwenden, gehen wir nun ein paar Verwaltungsaufgaben für Ihre Arbeitskopie durch.

Entsorgen einer Arbeitskopie

Subversion merkt sich weder den Zustand noch das Vorhandensein einer Arbeitskopie auf dem Server, so dass serverseitig kein Aufwand für Arbeitskopien anfällt. Dementsprechend besteht keine Notwendigkeit, dem Server mitzuteilen, dass Sie vorhaben, eine Arbeitskopie zu löschen.

Falls die Wahrscheinlichkeit besteht, dass Sie eine Arbeitskopie wiederverwenden möchten, ist es nicht verkehrt, sie einfach auf der Platte zu lassen, bis Sie sie wieder benutzen wollen. Zu diesem Zeitpunkt reicht lediglich ein svn update zum Aktualisieren, und sie ist gebrauchsfertig.

Falls Sie die Arbeitskopie jedoch bestimmt nicht mehr verwenden möchten, können Sie sie ruhig löschen; jedoch sollten Sie vorher darin nach unversionierten Dateien suchen. Um diese Dateien zu finden, rufen Sie svn status auf und untersuchen alle Dateien, denen ein ? voransteht, um sicherzugehen, dass sie nicht wichtig sind. Wenn Sie die Untersuchung abgeschlossen haben, können Sie Ihre Arbeitskopie ruhig löschen.

Wiederherstellung nach einer Unterbrechung

Wenn Subversion Ihre Arbeitskopie (oder irgendwelche Informationen in .svn) verändert, versucht es das so sicher wie möglich zu machen. Bevor die Arbeitskopie geändert wird, schreibt Subversion seine Absichten in eine Protokolldatei. Dann führt es die Befehle in der Protokolldatei aus, um die Änderungen anzuwenden, wobei es während der Arbeit den relevanten Teil der Arbeitskopie sperrt, um andere Clients davon abzuhalten, während der Änderung auf die Arbeitskopie zuzugreifen. Zuletzt entfernt Subversion die Protokolldatei. Architektonisch ist dies ähnlich wie bei einem Dateisystem mit Journal. Falls eine Subversion-Operation unterbrochen wird (z.B. wenn der Prozess abgeschossen wird oder der Rechner abstürzt), bleibt die Protokolldatei auf der Platte. Durch das erneute Ausführen der Protokolldatei kann Subversion die vorher begonnene Operation vervollständigen und Ihre Arbeitskopie gelangt wieder in einen konsistenten Zustand.

Genau das macht svn cleanup: Es durchsucht Ihre Arbeitskopie und führt etwaige übrig gebliebene Protokolldateien aus, wobei Sperren in der Arbeitskopie entfernt werden. Fall Ihnen Subversion jemals mitteilt, dass ein Teil Ihrer Arbeitskopie gesperrt ist, sollten Sie diesen Befehl aufrufen. Darüberhinaus zeigt svn status ein L neben gesperrten Objekten an:

$ svn status
  L    somedir
M      somedir/foo.c

$ svn cleanup
$ svn status
M      somedir/foo.c

Zusammenfassung

Nun haben wir die meisten der Subversion-Client-Befehle behandelt. Erwähnenswerte Ausnahmen sind diejenigen, die sich mit dem Branchen und Mergen befassen (siehe Kapitel 4, Verzweigen und Zusammenführen) sowie mit Propertys (siehe „Properties“). Jedoch möchten Sie vielleicht einen Augenblick damit verbringen, um durch Kapitel 9, Die komplette Subversion Referenz zu blättern, um ein Gefühl für all die verschiedenen Befehle zu bekommen, über die Subversion verfügt – und wie Sie sie verwenden können, um Ihre Arbeit zu erleichtern.




[3] Natürlich sind Sie nicht ernsthaft besorgt – erstens, weil Sie wissen, dass Sie nichts wirklich aus Subversion löschen können und zweitens, weil Ihr Subversion-Passwort nicht das gleiche ist wie irgendein anderes Ihrer 3 Millionen Passwörter, nicht wahr?

[4] Selbstverständlich wird nichts jemals vollständig aus dem Repository gelöscht – lediglich aus der HEAD-Revision des Repositorys. Sie können alles was Sie gelöscht haben zurückholen, indem Sie eine Revision auschecken (oder hierauf aktualisieren), die älter ist, als die Revision Ihrer Löschung. Siehe auch „Zurückholen gelöschter Objekte“.

[5] Und Sie haben keine WLAN-Karte. Sie dachten wohl, Sie kriegen uns, was?

[6] Und wenn Sie danach fragen, wird man Sie wahrscheinlich auf einer Schiene aus der Stadt tragen.

[7] Sehen Sie? Wir haben Ihnen gesagt, dass Subversion eine Zeitmaschine sei.

Kapitel 3. Advanced Topics

If you've been reading this book chapter by chapter, from start to finish, you should by now have acquired enough knowledge to use the Subversion client to perform the most common version control operations. You understand how to check out a working copy from a Subversion repository. You are comfortable with submitting and receiving changes using the svn commit and svn update operations. You've probably even developed a reflex that causes you to run the svn status command almost unconsciously. For all intents and purposes, you are ready to use Subversion in a typical environment.

But the Subversion feature set doesn't stop at common version control operations. It has other bits of functionality besides just communicating file and directory changes to and from a central repository.

This chapter highlights some of Subversion's features that, while important, aren't part of the typical user's daily routine. It assumes that you are familiar with Subversion's basic file and directory versioning capabilities. If you aren't, you'll want to first read Kapitel 1, Grundlegende Konzepte and Kapitel 2, Grundlegende Benutzung. Once you've mastered those basics and consumed this chapter, you'll be a Subversion power user!

Revision Specifiers

As we described in „Revisionen“, revision numbers in Subversion are pretty straightforward—integers that keep getting larger as you commit more changes to your versioned data. Still, it doesn't take long before you can no longer remember exactly what happened in each and every revision. Fortunately, the typical Subversion workflow doesn't often demand that you supply arbitrary revisions to the Subversion operations you perform. For operations that do require a revision specifier, you generally supply a revision number that you saw in a commit email, in the output of some other Subversion operation, or in some other context that would give meaning to that particular number.

But occasionally, you need to pinpoint a moment in time for which you don't already have a revision number memorized or handy. So besides the integer revision numbers, svn allows as input some additional forms of revision specifiers: revision keywords and revision dates.

[Anmerkung]Anmerkung

The various forms of Subversion revision specifiers can be mixed and matched when used to specify revision ranges. For example, you can use -r REV1:REV2 where REV1 is a revision keyword and REV2 is a revision number, or where REV1 is a date and REV2 is a revision keyword, and so on. The individual revision specifiers are independently evaluated, so you can put whatever you want on the opposite sides of that colon.

Revision Keywords

The Subversion client understands a number of revision keywords. These keywords can be used instead of integer arguments to the --revision (-r) option, and are resolved into specific revision numbers by Subversion:

HEAD

The latest (or youngest) revision in the repository.

BASE

The revision number of an item in a working copy. If the item has been locally modified, this refers to the way the item appears without those local modifications.

COMMITTED

The most recent revision prior to, or equal to, BASE, in which an item changed.

PREV

The revision immediately before the last revision in which an item changed. Technically, this boils down to COMMITTED−1.

As can be derived from their descriptions, the PREV, BASE, and COMMITTED revision keywords are used only when referring to a working copy path—they don't apply to repository URLs. HEAD, on the other hand, can be used in conjunction with both of these path types.

Here are some examples of revision keywords in action:

$ svn diff -r PREV:COMMITTED foo.c
# shows the last change committed to foo.c

$ svn log -r HEAD
# shows log message for the latest repository commit

$ svn diff -r HEAD
# compares your working copy (with all of its local changes) to the
# latest version of that tree in the repository

$ svn diff -r BASE:HEAD foo.c
# compares the unmodified version of foo.c with the latest version of
# foo.c in the repository

$ svn log -r BASE:HEAD
# shows all commit logs for the current versioned directory since you
# last updated

$ svn update -r PREV foo.c
# rewinds the last change on foo.c, decreasing foo.c's working revision

$ svn diff -r BASE:14 foo.c
# compares the unmodified version of foo.c with the way foo.c looked
# in revision 14

Revision Dates

Revision numbers reveal nothing about the world outside the version control system, but sometimes you need to correlate a moment in real time with a moment in version history. To facilitate this, the --revision (-r) option can also accept as input date specifiers wrapped in curly braces ({ and }). Subversion accepts the standard ISO-8601 date and time formats, plus a few others. Here are some examples. (Remember to use quotes around any date that contains spaces.)

$ svn checkout -r {2006-02-17}
$ svn checkout -r {15:30}
$ svn checkout -r {15:30:00.200000}
$ svn checkout -r {"2006-02-17 15:30"}
$ svn checkout -r {"2006-02-17 15:30 +0230"}
$ svn checkout -r {2006-02-17T15:30}
$ svn checkout -r {2006-02-17T15:30Z}
$ svn checkout -r {2006-02-17T15:30-04:00}
$ svn checkout -r {20060217T1530}
$ svn checkout -r {20060217T1530Z}
$ svn checkout -r {20060217T1530-0500}
…

When you specify a date, Subversion resolves that date to the most recent revision of the repository as of that date, and then continues to operate against that resolved revision number:

$ svn log -r {2006-11-28}
------------------------------------------------------------------------
r12 | ira | 2006-11-27 12:31:51 -0600 (Mon, 27 Nov 2006) | 6 lines
…

You can also use a range of dates. Subversion will find all revisions between both dates, inclusive:

$ svn log -r {2006-11-20}:{2006-11-29}
…
[Warnung]Warnung

Since the timestamp of a revision is stored as an unversioned, modifiable property of the revision (see „Properties“), revision timestamps can be changed to represent complete falsifications of true chronology, or even removed altogether. Subversion's ability to correctly convert revision dates into real revision numbers depends on revision datestamps maintaining a sequential ordering—the younger the revision, the younger its timestamp. If this ordering isn't maintained, you will likely find that trying to use dates to specify revision ranges in your repository doesn't always return the data you might have expected.

Properties

We've already covered in detail how Subversion stores and retrieves various versions of files and directories in its repository. Whole chapters have been devoted to this most fundamental piece of functionality provided by the tool. And if the versioning support stopped there, Subversion would still be complete from a version control perspective.

But it doesn't stop there.

In addition to versioning your directories and files, Subversion provides interfaces for adding, modifying, and removing versioned metadata on each of your versioned directories and files. We refer to this metadata as properties, and they can be thought of as two-column tables that map property names to arbitrary values attached to each item in your working copy. Generally speaking, the names and values of the properties can be whatever you want them to be, with the constraint that the names must contain only ASCII characters. And the best part about these properties is that they, too, are versioned, just like the textual contents of your files. You can modify, commit, and revert property changes as easily as you can file content changes. And the sending and receiving of property changes occurs as part of your typical commit and update operations—you don't have to change your basic processes to accommodate them.

[Anmerkung]Anmerkung

Subversion has reserved the set of properties whose names begin with svn: as its own. While there are only a handful of such properties in use today, you should avoid creating custom properties for your own needs whose names begin with this prefix. Otherwise, you run the risk that a future release of Subversion will grow support for a feature or behavior driven by a property of the same name but with perhaps an entirely different interpretation.

Properties show up elsewhere in Subversion, too. Just as files and directories may have arbitrary property names and values attached to them, each revision as a whole may have arbitrary properties attached to it. The same constraints apply—human-readable names and anything-you-want binary values. The main difference is that revision properties are not versioned. In other words, if you change the value of, or delete, a revision property, there's no way, within the scope of Subversion's functionality, to recover the previous value.

Subversion has no particular policy regarding the use of properties. It asks only that you not use property names that begin with the prefix svn:. That's the namespace that it sets aside for its own use. And Subversion does, in fact, use properties—both the versioned and unversioned variety. Certain versioned properties have special meaning or effects when found on files and directories, or they house a particular bit of information about the revisions on which they are found. Certain revision properties are automatically attached to revisions by Subversion's commit process, and they carry information about the revision. Most of these properties are mentioned elsewhere in this or other chapters as part of the more general topics to which they are related. For an exhaustive list of Subversion's predefined properties, see „Subversion-Propertys“.

In this section, we will examine the utility—both to users of Subversion and to Subversion itself—of property support. You'll learn about the property-related svn subcommands and how property modifications affect your normal Subversion workflow.

Why Properties?

Just as Subversion uses properties to store extra information about the files, directories, and revisions that it contains, you might also find properties to be of similar use. You might find it useful to have a place close to your versioned data to hang custom metadata about that data.

Say you wish to design a web site that houses many digital photos and displays them with captions and a datestamp. Now, your set of photos is constantly changing, so you'd like to have as much of this site automated as possible. These photos can be quite large, so as is common with sites of this nature, you want to provide smaller thumbnail images to your site visitors.

Now, you can get this functionality using traditional files. That is, you can have your image123.jpg and an image123-thumbnail.jpg side by side in a directory. Or if you want to keep the filenames the same, you might have your thumbnails in a different directory, such as thumbnails/image123.jpg. You can also store your captions and datestamps in a similar fashion, again separated from the original image file. But the problem here is that your collection of files multiplies with each new photo added to the site.

Now consider the same web site deployed in a way that makes use of Subversion's file properties. Imagine having a single image file, image123.jpg, with properties set on that file that are named caption, datestamp, and even thumbnail. Now your working copy directory looks much more manageable—in fact, it looks to the casual browser like there are nothing but image files in it. But your automation scripts know better. They know that they can use svn (or better yet, they can use the Subversion language bindings—see „Benutzung der APIs“) to dig out the extra information that your site needs to display without having to read an index file or play path manipulation games.

[Anmerkung]Anmerkung

While Subversion places few restrictions on the names and values you use for properties, it has not been designed to optimally carry large property values or large sets of properties on a given file or directory. Subversion commonly holds all the property names and values associated with a single item in memory at the same time, which can cause detrimental performance or failed operations when extremely large property sets are used.

Custom revision properties are also frequently used. One common such use is a property whose value contains an issue tracker ID with which the revision is associated, perhaps because the change made in that revision fixes a bug filed in the tracker issue with that ID. Other uses include hanging more friendly names on the revision—it might be hard to remember that revision 1935 was a fully tested revision. But if there's, say, a test-results property on that revision with the value all passing, that's meaningful information to have.

Manipulating Properties

The svn program affords a few ways to add or modify file and directory properties. For properties with short, human-readable values, perhaps the simplest way to add a new property is to specify the property name and value on the command line of the svn propset subcommand:

$ svn propset copyright '(c) 2006 Red-Bean Software' calc/button.c
property 'copyright' set on 'calc/button.c'
$

But we've been touting the flexibility that Subversion offers for your property values. And if you are planning to have a multiline textual, or even binary, property value, you probably do not want to supply that value on the command line. So the svn propset subcommand takes a --file (-F) option for specifying the name of a file that contains the new property value.

$ svn propset license -F /path/to/LICENSE calc/button.c
property 'license' set on 'calc/button.c'
$

There are some restrictions on the names you can use for properties. A property name must start with a letter, a colon (:), or an underscore (_); after that, you can also use digits, hyphens (-), and periods (.). [8]

In addition to the propset command, the svn program supplies the propedit command. This command uses the configured editor program (see „Config“) to add or modify properties. When you run the command, svn invokes your editor program on a temporary file that contains the current value of the property (or that is empty, if you are adding a new property). Then, you just modify that value in your editor program until it represents the new value you wish to store for the property, save the temporary file, and then exit the editor program. If Subversion detects that you've actually changed the existing value of the property, it will accept that as the new property value. If you exit your editor without making any changes, no property modification will occur:

$ svn propedit copyright calc/button.c  ### exit the editor without changes
No changes to property 'copyright' on 'calc/button.c'
$

We should note that, as with other svn subcommands, those related to properties can act on multiple paths at once. This enables you to modify properties on whole sets of files with a single command. For example, we could have done the following:

$ svn propset copyright '(c) 2006 Red-Bean Software' calc/*
property 'copyright' set on 'calc/Makefile'
property 'copyright' set on 'calc/button.c'
property 'copyright' set on 'calc/integer.c'
…
$

All of this property adding and editing isn't really very useful if you can't easily get the stored property value. So the svn program supplies two subcommands for displaying the names and values of properties stored on files and directories. The svn proplist command will list the names of properties that exist on a path. Once you know the names of the properties on the node, you can request their values individually using svn propget. This command will, given a property name and a path (or set of paths), print the value of the property to the standard output stream.

$ svn proplist calc/button.c
Properties on 'calc/button.c':
  copyright
  license
$ svn propget copyright calc/button.c
(c) 2006 Red-Bean Software

There's even a variation of the proplist command that will list both the name and the value for all of the properties. Simply supply the --verbose (-v) option.

$ svn proplist -v calc/button.c
Properties on 'calc/button.c':
  copyright : (c) 2006 Red-Bean Software
  license : ================================================================
Copyright (c) 2006 Red-Bean Software.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions 
are met:

1. Redistributions of source code must retain the above copyright
notice, this list of conditions, and the recipe for Fitz's famous
red-beans-and-rice.
…

The last property-related subcommand is propdel. Since Subversion allows you to store properties with empty values, you can't remove a property altogether using svn propedit or svn propset. For example, this command will not yield the desired effect:

$ svn propset license '' calc/button.c
property 'license' set on 'calc/button.c'
$ svn proplist -v calc/button.c
Properties on 'calc/button.c':
  copyright : (c) 2006 Red-Bean Software
  license : 
$

You need to use the propdel subcommand to delete properties altogether. The syntax is similar to the other property commands:

$ svn propdel license calc/button.c
property 'license' deleted from 'calc/button.c'.
$ svn proplist -v calc/button.c
Properties on 'calc/button.c':
  copyright : (c) 2006 Red-Bean Software
$

Remember those unversioned revision properties? You can modify those, too, using the same svn subcommands that we just described. Simply add the --revprop command-line parameter and specify the revision whose property you wish to modify. Since revisions are global, you don't need to specify a target path to these property-related commands so long as you are positioned in a working copy of the repository whose revision property you wish to modify. Otherwise, you can simply provide the URL of any path in the repository of interest (including the repository's root URL). For example, you might want to replace the commit log message of an existing revision. [9] If your current working directory is part of a working copy of your repository, you can simply run the svn propset command with no target path:

$ svn propset svn:log '* button.c: Fix a compiler warning.' -r11 --revprop
property 'svn:log' set on repository revision '11'
$

But even if you haven't checked out a working copy from that repository, you can still effect the property change by providing the repository's root URL:

$ svn propset svn:log '* button.c: Fix a compiler warning.' -r11 --revprop \
              http://svn.example.com/repos/project
property 'svn:log' set on repository revision '11'
$

Note that the ability to modify these unversioned properties must be explicitly added by the repository administrator (see „Berichtigung des Protokolleintrags“). That's because the properties aren't versioned, so you run the risk of losing information if you aren't careful with your edits. The repository administrator can set up methods to protect against this loss, and by default, modification of unversioned properties is disabled.

[Tipp]Tipp

Users should, where possible, use svn propedit instead of svn propset. While the end result of the commands is identical, the former will allow them to see the current value of the property that they are about to change, which helps them to verify that they are, in fact, making the change they think they are making. This is especially true when modifying unversioned revision properties. Also, it is significantly easier to modify multiline property values in a text editor than at the command line.

Properties and the Subversion Workflow

Now that you are familiar with all of the property-related svn subcommands, let's see how property modifications affect the usual Subversion workflow. As we mentioned earlier, file and directory properties are versioned, just like your file contents. As a result, Subversion provides the same opportunities for merging—cleanly or with conflicts—someone else's modifications into your own.

As with file contents, your property changes are local modifications, made permanent only when you commit them to the repository with svn commit. Your property changes can be easily unmade, too—the svn revert command will restore your files and directories to their unedited states—contents, properties, and all. Also, you can receive interesting information about the state of your file and directory properties by using the svn status and svn diff commands.

$ svn status calc/button.c
 M     calc/button.c
$ svn diff calc/button.c
Property changes on: calc/button.c
___________________________________________________________________
Name: copyright
   + (c) 2006 Red-Bean Software

$

Notice how the status subcommand displays M in the second column instead of the first. That is because we have modified the properties on calc/button.c, but not its textual contents. Had we changed both, we would have seen M in the first column, too. (We cover svn status in „Verschaffen Sie sich einen Überblick über Ihre Änderungen“).

You might also have noticed the nonstandard way that Subversion currently displays property differences. You can still use svn diff and redirect its output to create a usable patch file. The patch program will ignore property patches—as a rule, it ignores any noise it can't understand. This does, unfortunately, mean that to fully apply a patch generated by svn diff, any property modifications will need to be applied by hand.

Automatic Property Setting

Properties are a powerful feature of Subversion, acting as key components of many Subversion features discussed elsewhere in this and other chapters—textual diff and merge support, keyword substitution, newline translation, and so on. But to get the full benefit of properties, they must be set on the right files and directories. Unfortunately, that step can be easily forgotten in the routine of things, especially since failing to set a property doesn't usually result in an obvious error (at least compared to, say, failing to add a file to version control). To help your properties get applied to the places that need them, Subversion provides a couple of simple but useful features.

Whenever you introduce a file to version control using the svn add or svn import commands, Subversion tries to assist by setting some common file properties automatically. First, on operating systems whose filesystems support an execute permission bit, Subversion will automatically set the svn:executable property on newly added or imported files whose execute bit is enabled. (See „File Executability“ later in this chapter for more about this property.)

Second, Subversion tries to determine the file's MIME type. If you've configured a mime-types-files runtime configuration parameter, Subversion will try to find a MIME type mapping in that file for your file's extension. If it finds such a mapping, it will set your file's svn:mime-type property to the MIME type it found. If no mapping file is configured, or no mapping for your file's extension could be found, Subversion runs a very basic heuristic to determine whether the file contains nontextual content. If so, it automatically sets the svn:mime-type property on that file to application/octet-stream (the generic this is a collection of bytes MIME type). Of course, if Subversion guesses incorrectly, or if you wish to set the svn:mime-type property to something more precise—perhaps image/png or application/x-shockwave-flash—you can always remove or edit that property. (For more on Subversion's use of MIME types, see „File Content Type“ later in this chapter.)

Subversion also provides, via its runtime configuration system (see „Laufzeit-Konfigurationsbereich“), a more flexible automatic property setting feature that allows you to create mappings of filename patterns to property names and values. Once again, these mappings affect adds and imports, and can not only override the default MIME type decision made by Subversion during those operations, but can also set additional Subversion or custom properties, too. For example, you might create a mapping that says that anytime you add JPEG files—ones whose names match the pattern *.jpg—Subversion should automatically set the svn:mime-type property on those files to image/jpeg. Or perhaps any files that match *.cpp should have svn:eol-style set to native, and svn:keywords set to Id. Automatic property support is perhaps the handiest property-related tool in the Subversion toolbox. See „Config“ for more about configuring that support.

File Portability

Fortunately for Subversion users who routinely find themselves on different computers with different operating systems, Subversion's command-line program behaves almost identically on all those systems. If you know how to wield svn on one platform, you know how to wield it everywhere.

However, the same is not always true of other general classes of software or of the actual files you keep in Subversion. For example, on a Windows machine, the definition of a text file would be similar to that used on a Linux box, but with a key difference—the character sequences used to mark the ends of the lines of those files. There are other differences, too. Unix platforms have (and Subversion supports) symbolic links; Windows does not. Unix platforms use filesystem permission to determine executability; Windows uses filename extensions.

Because Subversion is in no position to unite the whole world in common definitions and implementations of all of these things, the best it can do is to try to help make your life simpler when you need to work with your versioned files and directories on multiple computers and operating systems. This section describes some of the ways Subversion does this.

File Content Type

Subversion joins the ranks of the many applications that recognize and make use of Multipurpose Internet Mail Extensions (MIME) content types. Besides being a general-purpose storage location for a file's content type, the value of the svn:mime-type file property determines some behavioral characteristics of Subversion itself.

For example, one of the benefits that Subversion typically provides is contextual, line-based merging of changes received from the server during an update into your working file. But for files containing nontextual data, there is often no concept of a line. So, for versioned files whose svn:mime-type property is set to a nontextual MIME type (generally, something that doesn't begin with text/, though there are exceptions), Subversion does not attempt to perform contextual merges during updates. Instead, any time you have locally modified a binary working copy file that is also being updated, your file is left untouched and Subversion creates two new files. One file has a .oldrev extension and contains the BASE revision of the file. The other file has a .newrev extension and contains the contents of the updated revision of the file. This behavior is really for the protection of the user against failed attempts at performing contextual merges on files that simply cannot be contextually merged.

[Warnung]Warnung

The svn:mime-type property, when set to a value that does not indicate textual file contents, can cause some unexpected behaviors with respect to other properties. For example, since the idea of line endings (and therefore, line-ending conversion) makes no sense when applied to nontextual files, Subversion will prevent you from setting the svn:eol-style property on such files. This is obvious when attempted on a single file target—svn propset will error out. But it might not be as clear if you perform a recursive property set, where Subversion will silently skip over files that it deems unsuitable for a given property.

Beginning in Subversion 1.5, users can configure a new mime-types-file runtime configuration parameter, which identifies the location of a MIME types mapping file. Subversion will consult this mapping file to determine the MIME type of newly added and imported files.

Also, if the svn:mime-type property is set, then the Subversion Apache module will use its value to populate the Content-type: HTTP header when responding to GET requests. This gives your web browser a crucial clue about how to display a file when you use it to peruse your Subversion repository's contents.

File Executability

On many operating systems, the ability to execute a file as a command is governed by the presence of an execute permission bit. This bit usually defaults to being disabled, and must be explicitly enabled by the user for each file that needs it. But it would be a monumental hassle to have to remember exactly which files in a freshly checked-out working copy were supposed to have their executable bits toggled on, and then to have to do that toggling. So, Subversion provides the svn:executable property as a way to specify that the executable bit for the file on which that property is set should be enabled, and Subversion honors that request when populating working copies with such files.

This property has no effect on filesystems that have no concept of an executable permission bit, such as FAT32 and NTFS. [11] Also, although it has no defined values, Subversion will force its value to * when setting this property. Finally, this property is valid only on files, not on directories.

End-of-Line Character Sequences

Unless otherwise noted using a versioned file's svn:mime-type property, Subversion assumes the file contains human-readable data. Generally speaking, Subversion uses this knowledge only to determine whether contextual difference reports for that file are possible. Otherwise, to Subversion, bytes are bytes.

This means that by default, Subversion doesn't pay any attention to the type of end-of-line (EOL) markers used in your files. Unfortunately, different operating systems have different conventions about which character sequences represent the end of a line of text in a file. For example, the usual line-ending token used by software on the Windows platform is a pair of ASCII control characters—a carriage return (CR) followed by a line feed (LF). Unix software, however, just uses the LF character to denote the end of a line.

Not all of the various tools on these operating systems understand files that contain line endings in a format that differs from the native line-ending style of the operating system on which they are running. So, typically, Unix programs treat the CR character present in Windows files as a regular character (usually rendered as ^M), and Windows programs combine all of the lines of a Unix file into one giant line because no carriage return-linefeed (or CRLF) character combination was found to denote the ends of the lines.

This sensitivity to foreign EOL markers can be frustrating for folks who share a file across different operating systems. For example, consider a source code file, and developers that edit this file on both Windows and Unix systems. If all the developers always use tools that preserve the line-ending style of the file, no problems occur.

But in practice, many common tools either fail to properly read a file with foreign EOL markers, or convert the file's line endings to the native style when the file is saved. If the former is true for a developer, he has to use an external conversion utility (such as dos2unix or its companion, unix2dos) to prepare the file for editing. The latter case requires no extra preparation. But both cases result in a file that differs from the original quite literally on every line! Prior to committing his changes, the user has two choices. Either he can use a conversion utility to restore the modified file to the same line-ending style that it was in before his edits were made, or he can simply commit the file—new EOL markers and all.

The result of scenarios like these include wasted time and unnecessary modifications to committed files. Wasted time is painful enough. But when commits change every line in a file, this complicates the job of determining which of those lines were changed in a nontrivial way. Where was that bug really fixed? On what line was a syntax error introduced?

The solution to this problem is the svn:eol-style property. When this property is set to a valid value, Subversion uses it to determine what special processing to perform on the file so that the file's line-ending style isn't flip-flopping with every commit that comes from a different operating system. The valid values are:

native

This causes the file to contain the EOL markers that are native to the operating system on which Subversion was run. In other words, if a user on a Windows machine checks out a working copy that contains a file with an svn:eol-style property set to native, that file will contain CRLF EOL markers. A Unix user checking out a working copy that contains the same file will see LF EOL markers in his copy of the file.

Note that Subversion will actually store the file in the repository using normalized LF EOL markers regardless of the operating system. This is basically transparent to the user, though.

CRLF

This causes the file to contain CRLF sequences for EOL markers, regardless of the operating system in use.

LF

This causes the file to contain LF characters for EOL markers, regardless of the operating system in use.

CR

This causes the file to contain CR characters for EOL markers, regardless of the operating system in use. This line-ending style is not very common.

Ignoring Unversioned Items

In any given working copy, there is a good chance that alongside all those versioned files and directories are other files and directories that are neither versioned nor intended to be. Text editors litter directories with backup files. Software compilers generate intermediate—or even final—files that you typically wouldn't bother to version. And users themselves drop various other files and directories wherever they see fit, often in version control working copies.

It's ludicrous to expect Subversion working copies to be somehow impervious to this kind of clutter and impurity. In fact, Subversion counts it as a feature that its working copies are just typical directories, just like unversioned trees. But these not-to-be-versioned files and directories can cause some annoyance for Subversion users. For example, because the svn add and svn import commands act recursively by default and don't know which files in a given tree you do and don't wish to version, it's easy to accidentally add stuff to version control that you didn't mean to. And because svn status reports, by default, every item of interest in a working copy—including unversioned files and directories—its output can get quite noisy where many of these things exist.

So Subversion provides two ways for telling it which files you would prefer that it simply disregard. One of the ways involves the use of Subversion's runtime configuration system (see „Laufzeit-Konfigurationsbereich“), and therefore applies to all the Subversion operations that make use of that runtime configuration—generally those performed on a particular computer or by a particular user of a computer. The other way makes use of Subversion's directory property support and is more tightly bound to the versioned tree itself, and therefore affects everyone who has a working copy of that tree. Both of the mechanisms use file patterns (strings of literal and special wildcard characters used to match against filenames) to decide which files to ignore.

The Subversion runtime configuration system provides an option, global-ignores, whose value is a whitespace-delimited collection of file patterns. The Subversion client checks these patterns against the names of the files that are candidates for addition to version control, as well as to unversioned files that the svn status command notices. If any file's name matches one of the patterns, Subversion will basically act as if the file didn't exist at all. This is really useful for the kinds of files that you almost never want to version, such as editor backup files such as Emacs' *~ and .*~ files.

When found on a versioned directory, the svn:ignore property is expected to contain a list of newline-delimited file patterns that Subversion should use to determine ignorable objects in that same directory. These patterns do not override those found in the global-ignores runtime configuration option, but are instead appended to that list. And it's worth noting again that, unlike the global-ignores option, the patterns found in the svn:ignore property apply only to the directory on which that property is set, and not to any of its subdirectories. The svn:ignore property is a good way to tell Subversion to ignore files that are likely to be present in every user's working copy of that directory, such as compiler output or—to use an example more appropriate to this book—the HTML, PDF, or PostScript files generated as the result of a conversion of some source DocBook XML files to a more legible output format.

[Anmerkung]Anmerkung

Subversion's support for ignorable file patterns extends only to the one-time process of adding unversioned files and directories to version control. Once an object is under Subversion's control, the ignore pattern mechanisms no longer apply to it. In other words, don't expect Subversion to avoid committing changes you've made to a versioned file simply because that file's name matches an ignore pattern—Subversion always notices all of its versioned objects.

The global list of ignore patterns tends to be more a matter of personal taste and ties more closely to a user's particular tool chain than to the details of any particular working copy's needs. So, the rest of this section will focus on the svn:ignore property and its uses.

Say you have the following output from svn status:

$ svn status calc
 M     calc/button.c
?      calc/calculator
?      calc/data.c
?      calc/debug_log
?      calc/debug_log.1
?      calc/debug_log.2.gz
?      calc/debug_log.3.gz

In this example, you have made some property modifications to button.c, but in your working copy, you also have some unversioned files: the latest calculator program that you've compiled from your source code, a source file named data.c, and a set of debugging output logfiles. Now, you know that your build system always results in the calculator program being generated. [12] And you know that your test suite always leaves those debugging logfiles lying around. These facts are true for all working copies of this project, not just your own. And you know that you aren't interested in seeing those things every time you run svn status, and you are pretty sure that nobody else is interested in them either. So you use svn propedit svn:ignore calc to add some ignore patterns to the calc directory. For example, you might add this as the new value of the svn:ignore property:

calculator
debug_log*

After you've added this property, you will now have a local property modification on the calc directory. But notice what else is different about your svn status output:

$ svn status
 M     calc
 M     calc/button.c
?      calc/data.c

Now, all that cruft is missing from the output! Your calculator compiled program and all those logfiles are still in your working copy; Subversion just isn't constantly reminding you that they are present and unversioned. And now with all the uninteresting noise removed from the display, you are left with more intriguing items—such as that source code file data.c that you probably forgot to add to version control.

Of course, this less-verbose report of your working copy status isn't the only one available. If you actually want to see the ignored files as part of the status report, you can pass the --no-ignore option to Subversion:

$ svn status --no-ignore
 M     calc
 M     calc/button.c
I      calc/calculator
?      calc/data.c
I      calc/debug_log
I      calc/debug_log.1
I      calc/debug_log.2.gz
I      calc/debug_log.3.gz

As mentioned earlier, the list of file patterns to ignore is also used by svn add and svn import. Both of these operations involve asking Subversion to begin managing some set of files and directories. Rather than force the user to pick and choose which files in a tree she wishes to start versioning, Subversion uses the ignore patterns—both the global and the per-directory lists—to determine which files should not be swept into the version control system as part of a larger recursive addition or import operation. And here again, you can use the --no-ignore option to tell Subversion ignore its ignores list and operate on all the files and directories present.

[Tipp]Tipp

Even if svn:ignore is set, you may run into problems if you use shell wildcards in a command. Shell wildcards are expanded into an explicit list of targets before Subversion operates on them, so running svn SUBCOMMAND * is just like running svn SUBCOMMAND file1 file2 file3 …. In the case of the svn add command, this has an effect similar to passing the --no-ignore option. So instead of using a wildcard, use svn add --force . to do a bulk scheduling of unversioned things for addition. The explicit target will ensure that the current directory isn't overlooked because of being already under version control, and the --force option will cause Subversion to crawl through that directory, adding unversioned files while still honoring the svn:ignore property and global-ignores runtime configuration variable. Be sure to also provide the --depth files option to the svn add command if you don't want a fully recursive crawl for things to add.

Keyword Substitution

Subversion has the ability to substitute keywords—pieces of useful, dynamic information about a versioned file—into the contents of the file itself. Keywords generally provide information about the last modification made to the file. Because this information changes each time the file changes, and more importantly, just after the file changes, it is a hassle for any process except the version control system to keep the data completely up to date. Left to human authors, the information would inevitably grow stale.

For example, say you have a document in which you would like to display the last date on which it was modified. You could burden every author of that document to, just before committing their changes, also tweak the part of the document that describes when it was last changed. But sooner or later, someone would forget to do that. Instead, simply ask Subversion to perform keyword substitution on the LastChangedDate keyword. You control where the keyword is inserted into your document by placing a keyword anchor at the desired location in the file. This anchor is just a string of text formatted as $KeywordName$.

All keywords are case-sensitive where they appear as anchors in files: you must use the correct capitalization for the keyword to be expanded. You should consider the value of the svn:keywords property to be case-sensitive, too—certain keyword names will be recognized regardless of case, but this behavior is deprecated.

Subversion defines the list of keywords available for substitution. That list contains the following five keywords, some of which have aliases that you can also use:

Date

This keyword describes the last time the file was known to have been changed in the repository, and is of the form $Date: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $. It may also be specified as LastChangedDate. Unlike the Id keyword, which uses UTC, the Date keyword displays dates using the local time zone.

Revision

This keyword describes the last known revision in which this file changed in the repository, and looks something like $Revision: 144 $. It may also be specified as LastChangedRevision or Rev.

Author

This keyword describes the last known user to change this file in the repository, and looks something like $Author: harry $. It may also be specified as LastChangedBy.

HeadURL

This keyword describes the full URL to the latest version of the file in the repository, and looks something like $HeadURL: http://svn.collab.net/repos/trunk/README $. It may be abbreviated as URL.

Id

This keyword is a compressed combination of the other keywords. Its substitution looks something like $Id: calc.c 148 2006-07-28 21:30:43Z sally $, and is interpreted to mean that the file calc.c was last changed in revision 148 on the evening of July 28, 2006 by the user sally. The date displayed by this keyword is in UTC, unlike that of the Date keyword (which uses the local time zone).

Several of the preceding descriptions use the phrase last known or similar wording. Keep in mind that keyword expansion is a client-side operation, and your client knows only about changes that have occurred in the repository when you update your working copy to include those changes. If you never update your working copy, your keywords will never expand to different values even if those versioned files are being changed regularly in the repository.

Simply adding keyword anchor text to your file does nothing special. Subversion will never attempt to perform textual substitutions on your file contents unless explicitly asked to do so. After all, you might be writing a document [13] about how to use keywords, and you don't want Subversion to substitute your beautiful examples of unsubstituted keyword anchors!

To tell Subversion whether to substitute keywords on a particular file, we again turn to the property-related subcommands. The svn:keywords property, when set on a versioned file, controls which keywords will be substituted on that file. The value is a space-delimited list of keyword names or aliases.

For example, say you have a versioned file named weather.txt that looks like this:

Here is the latest report from the front lines.
$LastChangedDate$
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.

With no svn:keywords property set on that file, Subversion will do nothing special. Now, let's enable substitution of the LastChangedDate keyword.

$ svn propset svn:keywords "Date Author" weather.txt
property 'svn:keywords' set on 'weather.txt'
$

Now you have made a local property modification on the weather.txt file. You will see no changes to the file's contents (unless you made some of your own prior to setting the property). Notice that the file contained a keyword anchor for the Rev keyword, yet we did not include that keyword in the property value we set. Subversion will happily ignore requests to substitute keywords that are not present in the file and will not substitute keywords that are not present in the svn:keywords property value.

Immediately after you commit this property change, Subversion will update your working file with the new substitute text. Instead of seeing your keyword anchor $LastChangedDate$, you'll see its substituted result. That result also contains the name of the keyword and continues to be delimited by the dollar sign ($) characters. And as we predicted, the Rev keyword was not substituted because we didn't ask for it to be.

Note also that we set the svn:keywords property to Date Author, yet the keyword anchor used the alias $LastChangedDate$ and still expanded correctly:

Here is the latest report from the front lines.
$LastChangedDate: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.

If someone else now commits a change to weather.txt, your copy of that file will continue to display the same substituted keyword value as before—until you update your working copy. At that time, the keywords in your weather.txt file will be resubstituted with information that reflects the most recent known commit to that file.

Subversion 1.2 introduced a new variant of the keyword syntax, which brought additional, useful—though perhaps atypical—functionality. You can now tell Subversion to maintain a fixed length (in terms of the number of bytes consumed) for the substituted keyword. By using a double colon (::) after the keyword name, followed by a number of space characters, you define that fixed width. When Subversion goes to substitute your keyword for the keyword and its value, it will essentially replace only those space characters, leaving the overall width of the keyword field unchanged. If the substituted value is shorter than the defined field width, there will be extra padding characters (spaces) at the end of the substituted field; if it is too long, it is truncated with a special hash (#) character just before the final dollar sign terminator.

For example, say you have a document in which you have some section of tabular data reflecting the document's Subversion keywords. Using the original Subversion keyword substitution syntax, your file might look something like:

$Rev$:     Revision of last commit
$Author$:  Author of last commit
$Date$:    Date of last commit

Now, that looks nice and tabular at the start of things. But when you then commit that file (with keyword substitution enabled, of course), you see:

$Rev: 12 $:     Revision of last commit
$Author: harry $:  Author of last commit
$Date: 2006-03-15 02:33:03 -0500 (Wed, 15 Mar 2006) $:    Date of last commit

The result is not so beautiful. And you might be tempted to then adjust the file after the substitution so that it again looks tabular. But that holds only as long as the keyword values are the same width. If the last committed revision rolls into a new place value (say, from 99 to 100), or if another person with a longer username commits the file, stuff gets all crooked again. However, if you are using Subversion 1.2 or later, you can use the new fixed-length keyword syntax and define some field widths that seem sane, so your file might look like this:

$Rev::               $:  Revision of last commit
$Author::            $:  Author of last commit
$Date::              $:  Date of last commit

You commit this change to your file. This time, Subversion notices the new fixed-length keyword syntax and maintains the width of the fields as defined by the padding you placed between the double colon and the trailing dollar sign. After substitution, the width of the fields is completely unchanged—the short values for Rev and Author are padded with spaces, and the long Date field is truncated by a hash character:

$Rev:: 13            $:  Revision of last commit
$Author:: harry      $:  Author of last commit
$Date:: 2006-03-15 0#$:  Date of last commit

The use of fixed-length keywords is especially handy when performing substitutions into complex file formats that themselves use fixed-length fields for data, or for which the stored size of a given data field is overbearingly difficult to modify from outside the format's native application (such as for Microsoft Office documents).

[Warnung]Warnung

Be aware that because the width of a keyword field is measured in bytes, the potential for corruption of multibyte values exists. For example, a username that contains some multibyte UTF-8 characters might suffer truncation in the middle of the string of bytes that make up one of those characters. The result will be a mere truncation when viewed at the byte level, but will likely appear as a string with an incorrect or garbled final character when viewed as UTF-8 text. It is conceivable that certain applications, when asked to load the file, would notice the broken UTF-8 text and deem the entire file corrupt, refusing to operate on the file altogether. So, when limiting keywords to a fixed size, choose a size that allows for this type of byte-wise expansion.

Sparse Directories

By default, most Subversion operations on directories act in a recursive manner. For example, svn checkout creates a working copy with every file and directory in the specified area of the repository, descending recursively through the repository tree until the entire structure is copied to your local disk. Subversion 1.5 introduces a feature called sparse directories (or shallow checkouts) that allows you to easily check out a working copy—or a portion of a working copy—more shallowly than full recursion, with the freedom to bring in previously ignored files and subdirectories at a later time.

For example, say we have a repository with a tree of files and directories with names of the members of a human family with pets. (It's an odd example, to be sure, but bear with us.) A regular svn checkout operation will give us a working copy of the whole tree:

$ svn checkout file:///var/svn/repos mom
A    mom/son
A    mom/son/grandson
A    mom/daughter
A    mom/daughter/granddaughter1
A    mom/daughter/granddaughter1/bunny1.txt
A    mom/daughter/granddaughter1/bunny2.txt
A    mom/daughter/granddaughter2
A    mom/daughter/fishie.txt
A    mom/kitty1.txt
A    mom/doggie1.txt
Checked out revision 1.
$

Now, let's check out the same tree again, but this time we'll ask Subversion to give us only the topmost directory with none of its children at all:

$ svn checkout file:///var/svn/repos mom-empty --depth empty
Checked out revision 1
$

Notice that we added to our original svn checkout command line a new --depth option. This option is present on many of Subversion's subcommands and is similar to the --non-recursive (-N) and --recursive (-R) options. In fact, it combines, improves upon, supercedes, and ultimately obsoletes these two older options. For starters, it expands the supported degrees of depth specification available to users, adding some previously unsupported (or inconsistently supported) depths. Here are the depth values that you can request for a given Subversion operation:

--depth empty

Include only the immediate target of the operation, not any of its file or directory children.

--depth files

Include the immediate target of the operation and any of its immediate file children.

--depth immediates

Include the immediate target of the operation and any of its immediate file or directory children. The directory children will themselves be empty.

--depth infinity

Include the immediate target, its file and directory children, its children's children, and so on to full recursion.

Of course, merely combining two existing options into one hardly constitutes a new feature worthy of a whole section in our book. Fortunately, there is more to this story. This idea of depth extends not just to the operations you perform with your Subversion client, but also as a description of a working copy citizen's ambient depth, which is the depth persistently recorded by the working copy for that item. Its key strength is this very persistence—the fact that it is sticky. The working copy remembers the depth you've selected for each item in it until you later change that depth selection; by default, Subversion commands operate on the working copy citizens present, regardless of their selected depth settings.

[Tipp]Tipp

You can check the recorded ambient depth of a working copy using the svn info command. If the ambient depth is anything other than infinite recursion, svn info will display a line describing that depth value:

$ svn info mom-immediates | grep '^Depth:'
Depth: immediates
$

Our previous examples demonstrated checkouts of infinite depth (the default for svn checkout) and empty depth. Let's look now at examples of the other depth values:

$ svn checkout file:///var/svn/repos mom-files --depth files
A    mom-files/kitty1.txt
A    mom-files/doggie1.txt
Checked out revision 1.
$ svn checkout file:///var/svn/repos mom-immediates --depth immediates
A    mom-immediates/son
A    mom-immediates/daughter
A    mom-immediates/kitty1.txt
A    mom-immediates/doggie1.txt
Checked out revision 1.
$

As described, each of these depths is something more than only the target, but something less than full recursion.

We've used svn checkout as an example here, but you'll find the --depth option present on many other Subversion commands, too. In those other commands, depth specification is a way to limit the scope of an operation to some depth, much like the way the older --non-recursive (-N) and --recursive (-R) options behave. This means that when operating on a working copy of some depth, while requesting an operation of a shallower depth, the operation is limited to that shallower depth. In fact, we can make an even more general statement: given a working copy of any arbitrary—even mixed—ambient depth, and a Subversion command with some requested operational depth, the command will maintain the ambient depth of the working copy members while still limiting the scope of the operation to the requested (or default) operational depth.

In addition to the --depth option, the svn update and svn switch subcommands also accept a second depth-related option: --set-depth. It is with this option that you can change the sticky depth of a working copy item. Watch what happens as we take our empty-depth checkout and gradually telescope it deeper using svn update --set-depth NEW-DEPTH TARGET:

$ svn update --set-depth files mom-empty
A    mom-empty/kittie1.txt
A    mom-empty/doggie1.txt
Updated to revision 1.
$ svn update --set-depth immediates mom-empty
A    mom-empty/son
A    mom-empty/daughter
Updated to revision 1.
$ svn update --set-depth infinity mom-empty
A    mom-empty/son/grandson
A    mom-empty/daughter/granddaughter1
A    mom-empty/daughter/granddaughter1/bunny1.txt
A    mom-empty/daughter/granddaughter1/bunny2.txt
A    mom-empty/daughter/granddaughter2
A    mom-empty/daughter/fishie1.txt
Updated to revision 1.
$

As we gradually increased our depth selection, the repository gave us more pieces of our tree.

In our example, we operated only on the root of our working copy, changing its ambient depth value. But we can independently change the ambient depth value of any subdirectory inside the working copy, too. Careful use of this ability allows us to flesh out only certain portions of the working copy tree, leaving other portions absent altogether (hence the sparse bit of the feature's name). Here's an example of how we might build out a portion of one branch of our family's tree, enable full recursion on another branch, and keep still other pieces pruned (absent from disk).

$ rm -rf mom-empty
$ svn checkout file:///var/svn/repos mom-empty --depth empty
Checked out revision 1.
$ svn update --set-depth empty mom-empty/son
A    mom-empty/son
Updated to revision 1.
$ svn update --set-depth empty mom-empty/daughter
A    mom-empty/daughter
Updated to revision 1.
$ svn update --set-depth infinity mom-empty/daughter/granddaughter1
A    mom-empty/daughter/granddaughter1
A    mom-empty/daughter/granddaughter1/bunny1.txt
A    mom-empty/daughter/granddaughter1/bunny2.txt
Updated to revision 1.
$

Fortunately, having a complex collection of ambient depths in a single working copy doesn't complicate the way you interact with that working copy. You can still make, revert, display, and commit local modifications in your working copy without providing any new options (including --depth and --set-depth) to the relevant subcommands. Even svn update works as it does elsewhere when no specific depth is provided—it updates the working copy targets that are present while honoring their sticky depths.

You might at this point be wondering, So what? When would I use this? One scenario where this feature finds utility is tied to a particular repository layout, specifically where you have many related or codependent projects or software modules living as siblings in a single repository location (trunk/project1, trunk/project2, trunk/project3, etc.). In such scenarios, it might be the case that you personally care about only a handful of those projects—maybe some primary project and a few other modules on which it depends. You can check out individual working copies of all of these things, but those working copies are disjoint and, as a result, it can be cumbersome to perform operations across several or all of them at the same time. The alternative is to use the sparse directories feature, building out a single working copy that contains only the modules you care about. You'd start with an empty-depth checkout of the common parent directory of the projects, and then update with infinite depth only the items you wish to have, like we demonstrated in the previous example. Think of it like an opt-in system for working copy citizens.

Subversion 1.5's implementation of shallow checkouts is good but does not support a couple of interesting behaviors. First, you cannot de-telescope a working copy item. Running svn update --set-depth empty in an infinite-depth working copy will not have the effect of discarding everything but the topmost directory—it will simply error out. Second, there is no depth value to indicate that you wish an item to be explicitly excluded. You have to do implicit exclusion of an item by including everything else.

Locking

Subversion's copy-modify-merge version control model lives and dies on its data merging algorithms—specifically on how well those algorithms perform when trying to resolve conflicts caused by multiple users modifying the same file concurrently. Subversion itself provides only one such algorithm: a three-way differencing algorithm that is smart enough to handle data at a granularity of a single line of text. Subversion also allows you to supplement its content merge processing with external differencing utilities (as described in „Externes diff3“), some of which may do an even better job, perhaps providing granularity of a word or a single character of text. But common among those algorithms is that they generally work only on text files. The landscape starts to look pretty grim when you start talking about content merges of nontextual file formats. And when you can't find a tool that can handle that type of merging, you begin to run into problems with the copy-modify-merge model.

Let's look at a real-life example of where this model runs aground. Harry and Sally are both graphic designers working on the same project, a bit of marketing collateral for an automobile mechanic. Central to the design of a particular poster is an image of a car in need of some bodywork, stored in a file using the PNG image format. The poster's layout is almost finished, and both Harry and Sally are pleased with the particular photo they chose for their damaged car—a baby blue 1967 Ford Mustang with an unfortunate bit of crumpling on the left front fender.

Now, as is common in graphic design work, there's a change in plans, which causes the car's color to be a concern. So Sally updates her working copy to HEAD, fires up her photo-editing software, and sets about tweaking the image so that the car is now cherry red. Meanwhile, Harry, feeling particularly inspired that day, decides that the image would have greater impact if the car also appears to have suffered greater impact. He, too, updates to HEAD, and then draws some cracks on the vehicle's windshield. He manages to finish his work before Sally finishes hers, and after admiring the fruits of his undeniable talent, he commits the modified image. Shortly thereafter, Sally is finished with the car's new finish and tries to commit her changes. But, as expected, Subversion fails the commit, informing Sally that her version of the image is now out of date.

Here's where the difficulty sets in. If Harry and Sally were making changes to a text file, Sally would simply update her working copy, receiving Harry's changes in the process. In the worst possible case, they would have modified the same region of the file, and Sally would have to work out by hand the proper resolution to the conflict. But these aren't text files—they are binary images. And while it's a simple matter to describe what one would expect the results of this content merge to be, there is precious little chance that any software exists that is smart enough to examine the common baseline image that each of these graphic artists worked against, the changes that Harry made, and the changes that Sally made, and then spit out an image of a busted-up red Mustang with a cracked windshield!

Of course, things would have gone more smoothly if Harry and Sally had serialized their modifications to the image—if, say, Harry had waited to draw his windshield cracks on Sally's now-red car, or if Sally had tweaked the color of a car whose windshield was already cracked. As is discussed in „Die „Kopieren – Ändern – Zusammenfassen“ - Lösung“, most of these types of problems go away entirely where perfect communication between Harry and Sally exists. [14] But as one's version control system is, in fact, one form of communication, it follows that having that software facilitate the serialization of nonparallelizable editing efforts is no bad thing. This is where Subversion's implementation of the lock-modify-unlock model steps into the spotlight. This is where we talk about Subversion's locking feature, which is similar to the reserved checkouts mechanisms of other version control systems.

Subversion's locking feature exists ultimately to minimize wasted time and effort. By allowing a user to programmatically claim the exclusive right to change a file in the repository, that user can be reasonably confident that any energy he invests on unmergeable changes won't be wasted—his commit of those changes will succeed. Also, because Subversion communicates to other users that serialization is in effect for a particular versioned object, those users can reasonably expect that the object is about to be changed by someone else. They, too, can then avoid wasting their time and energy on unmergeable changes that won't be committable due to eventual out-of-dateness.

When referring to Subversion's locking feature, one is actually talking about a fairly diverse collection of behaviors, which include the ability to lock a versioned file [15] (claiming the exclusive right to modify the file), to unlock that file (yielding that exclusive right to modify), to see reports about which files are locked and by whom, to annotate files for which locking before editing is strongly advised, and so on. In this section, we'll cover all of these facets of the larger locking feature.

Creating Locks

In the Subversion repository, a lock is a piece of metadata that grants exclusive access to one user to change a file. This user is said to be the lock owner. Each lock also has a unique identifier, typically a long string of characters, known as the lock token. The repository manages locks, ultimately handling their creation, enforcement, and removal. If any commit transaction attempts to modify or delete a locked file (or delete one of the parent directories of the file), the repository will demand two pieces of information—that the client performing the commit be authenticated as the lock owner, and that the lock token has been provided as part of the commit process as a form of proof that the client knows which lock it is using.

To demonstrate lock creation, let's refer back to our example of multiple graphic designers working on the same binary image files. Harry has decided to change a JPEG image. To prevent other people from committing changes to the file while he is modifying it (as well as alerting them that he is about to change it), he locks the file in the repository using the svn lock command.

$ svn lock banana.jpg -m "Editing file for tomorrow's release."
'banana.jpg' locked by user 'harry'.
$

The preceding example demonstrates a number of new things. First, notice that Harry passed the --message (-m) option to svn lock. Similar to svn commit, the svn lock command can take comments—via either --message (-m) or --file (-F)—to describe the reason for locking the file. Unlike svn commit, however, svn lock will not demand a message by launching your preferred text editor. Lock comments are optional, but still recommended to aid communication.

Second, the lock attempt succeeded. This means that the file wasn't already locked, and that Harry had the latest version of the file. If Harry's working copy of the file had been out of date, the repository would have rejected the request, forcing Harry to svn update and reattempt the locking command. The locking command would also have failed if the file had already been locked by someone else.

As you can see, the svn lock command prints confirmation of the successful lock. At this point, the fact that the file is locked becomes apparent in the output of the svn status and svn info reporting subcommands.

$ svn status
     K banana.jpg

$ svn info banana.jpg
Path: banana.jpg
Name: banana.jpg
URL: http://svn.example.com/repos/project/banana.jpg
Repository UUID: edb2f264-5ef2-0310-a47a-87b0ce17a8ec
Revision: 2198
Node Kind: file
Schedule: normal
Last Changed Author: frank
Last Changed Rev: 1950
Last Changed Date: 2006-03-15 12:43:04 -0600 (Wed, 15 Mar 2006)
Text Last Updated: 2006-06-08 19:23:07 -0500 (Thu, 08 Jun 2006)
Properties Last Updated: 2006-06-08 19:23:07 -0500 (Thu, 08 Jun 2006)
Checksum: 3b110d3b10638f5d1f4fe0f436a5a2a5
Lock Token: opaquelocktoken:0c0f600b-88f9-0310-9e48-355b44d4a58e
Lock Owner: harry
Lock Created: 2006-06-14 17:20:31 -0500 (Wed, 14 Jun 2006)
Lock Comment (1 line):
Editing file for tomorrow's release.

$

The fact that the svn info command, which does not contact the repository when run against working copy paths, can display the lock token reveals an important piece of information about those tokens: they are cached in the working copy. The presence of the lock token is critical. It gives the working copy authorization to make use of the lock later on. Also, the svn status command shows a K next to the file (short for locKed), indicating that the lock token is present.

Now that Harry has locked banana.jpg, Sally is unable to change or delete that file:

$ svn delete banana.jpg
D         banana.jpg
$ svn commit -m "Delete useless file."
Deleting       banana.jpg
svn: Commit failed (details follow):
svn: Server sent unexpected return value (423 Locked) in response to DELETE\
 request for '/repos/project/!svn/wrk/64bad3a9-96f9-0310-818a-df4224ddc35d/\
banana.jpg'
$

But Harry, after touching up the banana's shade of yellow, is able to commit his changes to the file. That's because he authenticates as the lock owner and also because his working copy holds the correct lock token:

$ svn status
M    K banana.jpg
$ svn commit -m "Make banana more yellow"
Sending        banana.jpg
Transmitting file data .
Committed revision 2201.
$ svn status
$

Notice that after the commit is finished, svn status shows that the lock token is no longer present in the working copy. This is the standard behavior of svn commit—it searches the working copy (or list of targets, if you provide such a list) for local modifications and sends all the lock tokens it encounters during this walk to the server as part of the commit transaction. After the commit completes successfully, all of the repository locks that were mentioned are released—even on files that weren't committed. This is meant to discourage users from being sloppy about locking or from holding locks for too long. If Harry haphazardly locks 30 files in a directory named images because he's unsure of which files he needs to change, yet changes only four of those files, when he runs svn commit images, the process will still release all 30 locks.

This behavior of automatically releasing locks can be overridden with the --no-unlock option to svn commit. This is best used for those times when you want to commit changes, but still plan to make more changes and thus need to retain existing locks. You can also make this your default behavior by setting the no-unlock runtime configuration option (see „Laufzeit-Konfigurationsbereich“).

Of course, locking a file doesn't oblige one to commit a change to it. The lock can be released at any time with a simple svn unlock command:

$ svn unlock banana.c
'banana.c' unlocked.

Discovering Locks

When a commit fails due to someone else's locks, it's fairly easy to learn about them. The easiest way is to run svn status --show-updates:

$ svn status -u
M              23   bar.c
M    O         32   raisin.jpg
       *       72   foo.h
Status against revision:     105
$

In this example, Sally can see not only that her copy of foo.h is out of date, but also that one of the two modified files she plans to commit is locked in the repository. The O symbol stands for Other, meaning that a lock exists on the file and was created by somebody else. If she were to attempt a commit, the lock on raisin.jpg would prevent it. Sally is left wondering who made the lock, when, and why. Once again, svn info has the answers:

$ svn info http://svn.example.com/repos/project/raisin.jpg
Path: raisin.jpg
Name: raisin.jpg
URL: http://svn.example.com/repos/project/raisin.jpg
Repository UUID: edb2f264-5ef2-0310-a47a-87b0ce17a8ec
Revision: 105
Node Kind: file
Last Changed Author: sally
Last Changed Rev: 32
Last Changed Date: 2006-01-25 12:43:04 -0600 (Sun, 25 Jan 2006)
Lock Token: opaquelocktoken:fc2b4dee-98f9-0310-abf3-653ff3226e6b
Lock Owner: harry
Lock Created: 2006-02-16 13:29:18 -0500 (Thu, 16 Feb 2006)
Lock Comment (1 line):
Need to make a quick tweak to this image.
$

Just as you can use svn info to examine objects in the working copy, you can also use it to examine objects in the repository. If the main argument to svn info is a working copy path, then all of the working copy's cached information is displayed; any mention of a lock means that the working copy is holding a lock token (if a file is locked by another user or in another working copy, svn info on a working copy path will show no lock information at all). If the main argument to svn info is a URL, the information reflects the latest version of an object in the repository, and any mention of a lock describes the current lock on the object.

So in this particular example, Sally can see that Harry locked the file on February 16 to make a quick tweak. It being June, she suspects that he probably forgot all about the lock. She might phone Harry to complain and ask him to release the lock. If he's unavailable, she might try to forcibly break the lock herself or ask an administrator to do so.

Breaking and Stealing Locks

A repository lock isn't sacred—in Subversion's default configuration state, locks can be released not only by the person who created them, but by anyone. When somebody other than the original lock creator destroys a lock, we refer to this as breaking the lock.

From the administrator's chair, it's simple to break locks. The svnlook and svnadmin programs have the ability to display and remove locks directly from the repository. (For more information about these tools, see „Der Werkzeugkasten eines Administrators“.)

$ svnadmin lslocks /var/svn/repos
Path: /project2/images/banana.jpg
UUID Token: opaquelocktoken:c32b4d88-e8fb-2310-abb3-153ff1236923
Owner: frank
Created: 2006-06-15 13:29:18 -0500 (Thu, 15 Jun 2006)
Expires: 
Comment (1 line):
Still improving the yellow color.

Path: /project/raisin.jpg
UUID Token: opaquelocktoken:fc2b4dee-98f9-0310-abf3-653ff3226e6b
Owner: harry
Created: 2006-02-16 13:29:18 -0500 (Thu, 16 Feb 2006)
Expires: 
Comment (1 line):
Need to make a quick tweak to this image.

$ svnadmin rmlocks /var/svn/repos /project/raisin.jpg
Removed lock on '/project/raisin.jpg'.
$

The more interesting option is to allow users to break each other's locks over the network. To do this, Sally simply needs to pass the --force to the svn unlock command:

$ svn status -u
M              23   bar.c
M    O         32   raisin.jpg
       *       72   foo.h
Status against revision:     105
$ svn unlock raisin.jpg
svn: 'raisin.jpg' is not locked in this working copy
$ svn info raisin.jpg | grep URL
URL: http://svn.example.com/repos/project/raisin.jpg
$ svn unlock http://svn.example.com/repos/project/raisin.jpg
svn: Unlock request failed: 403 Forbidden (http://svn.example.com)
$ svn unlock --force http://svn.example.com/repos/project/raisin.jpg
'raisin.jpg' unlocked.
$

Now, Sally's initial attempt to unlock failed because she ran svn unlock directly on her working copy of the file, and no lock token was present. To remove the lock directly from the repository, she needs to pass a URL to svn unlock. Her first attempt to unlock the URL fails, because she can't authenticate as the lock owner (nor does she have the lock token). But when she passes --force, the authentication and authorization requirements are ignored, and the remote lock is broken.

Simply breaking a lock may not be enough. In the running example, Sally may not only want to break Harry's long-forgotten lock, but relock the file for her own use. She can accomplish this by using svn unlock with --force and then svn lock back-to-back, but there's a small chance that somebody else might lock the file between the two commands. The simpler thing to do is to steal the lock, which involves breaking and relocking the file all in one atomic step. To do this, Sally passes the --force option to svn lock:

$ svn lock raisin.jpg
svn: Lock request failed: 423 Locked (http://svn.example.com)
$ svn lock --force raisin.jpg
'raisin.jpg' locked by user 'sally'.
$

In any case, whether the lock is broken or stolen, Harry may be in for a surprise. Harry's working copy still contains the original lock token, but that lock no longer exists. The lock token is said to be defunct. The lock represented by the lock token has either been broken (no longer in the repository) or stolen (replaced with a different lock). Either way, Harry can see this by asking svn status to contact the repository:

$ svn status
     K raisin.jpg
$ svn status -u
     B         32   raisin.jpg
$ svn update
  B  raisin.jpg
$ svn status
$

If the repository lock was broken, then svn status --show-updates displays a B (Broken) symbol next to the file. If a new lock exists in place of the old one, then a T (sTolen) symbol is shown. Finally, svn update notices any defunct lock tokens and removes them from the working copy.

Lock Communication

We've seen how svn lock and svn unlock can be used to create, release, break, and steal locks. This satisfies the goal of serializing commit access to a file. But what about the larger problem of preventing wasted time?

For example, suppose Harry locks an image file and then begins editing it. Meanwhile, miles away, Sally wants to do the same thing. She doesn't think to run svn status --show-updates, so she has no idea that Harry has already locked the file. She spends hours editing the file, and when she tries to commit her change, she discovers that either the file is locked or that she's out of date. Regardless, her changes aren't mergeable with Harry's. One of these two people has to throw away his or her work, and a lot of time has been wasted.

Subversion's solution to this problem is to provide a mechanism to remind users that a file ought to be locked before the editing begins. The mechanism is a special property: svn:needs-lock. If that property is attached to a file (regardless of its value, which is irrelevant), Subversion will try to use filesystem-level permissions to make the file read-only—unless, of course, the user has explicitly locked the file. When a lock token is present (as a result of using svn lock), the file becomes read/write. When the lock is released, the file becomes read-only again.

The theory, then, is that if the image file has this property attached, Sally would immediately notice something is strange when she opens the file for editing: many applications alert users immediately when a read-only file is opened for editing, and nearly all would prevent her from saving changes to the file. This reminds her to lock the file before editing, whereby she discovers the preexisting lock:

$ /usr/local/bin/gimp raisin.jpg
gimp: error: file is read-only!
$ ls -l raisin.jpg
-r--r--r--   1 sally   sally   215589 Jun  8 19:23 raisin.jpg
$ svn lock raisin.jpg
svn: Lock request failed: 423 Locked (http://svn.example.com)
$ svn info http://svn.example.com/repos/project/raisin.jpg | grep Lock
Lock Token: opaquelocktoken:fc2b4dee-98f9-0310-abf3-653ff3226e6b
Lock Owner: harry
Lock Created: 2006-06-08 07:29:18 -0500 (Thu, 08 June 2006)
Lock Comment (1 line):
Making some tweaks.  Locking for the next two hours.
$
[Tipp]Tipp

Users and administrators alike are encouraged to attach the svn:needs-lock property to any file that cannot be contextually merged. This is the primary technique for encouraging good locking habits and preventing wasted effort.

Note that this property is a communication tool that works independently from the locking system. In other words, any file can be locked, whether or not this property is present. And conversely, the presence of this property doesn't make the repository require a lock when committing.

Unfortunately, the system isn't flawless. It's possible that even when a file has the property, the read-only reminder won't always work. Sometimes applications misbehave and hijack the read-only file, silently allowing users to edit and save the file anyway. There's not much that Subversion can do in this situation—at the end of the day, there's simply no substitution for good interpersonal communication. [16]

Externals Definitions

Sometimes it is useful to construct a working copy that is made out of a number of different checkouts. For example, you may want different subdirectories to come from different locations in a repository or perhaps from different repositories altogether. You could certainly set up such a scenario by hand—using svn checkout to create the sort of nested working copy structure you are trying to achieve. But if this layout is important for everyone who uses your repository, every other user will need to perform the same checkout operations that you did.

Fortunately, Subversion provides support for externals definitions. An externals definition is a mapping of a local directory to the URL—and ideally a particular revision—of a versioned directory. In Subversion, you declare externals definitions in groups using the svn:externals property. You can create or modify this property using svn propset or svn propedit (see „Manipulating Properties“). It can be set on any versioned directory, and its value describes both the external repository location and the client-side directory to which that location should be checked out.

The convenience of the svn:externals property is that once it is set on a versioned directory, everyone who checks out a working copy with that directory also gets the benefit of the externals definition. In other words, once one person has made the effort to define the nested working copy structure, no one else has to bother—Subversion will, after checking out the original working copy, automatically also check out the external working copies.

[Warnung]Warnung

The relative target subdirectories of externals definitions must not already exist on your or other users' systems—Subversion will create them when it checks out the external working copy.

You also get in the externals definition design all the regular benefits of Subversion properties. The definitions are versioned. If you need to change an externals definition, you can do so using the regular property modification subcommands. When you commit a change to the svn:externals property, Subversion will synchronize the checked-out items against the changed externals definition when you next run svn update. The same thing will happen when others update their working copies and receive your changes to the externals definition.

[Tipp]Tipp

Because the svn:externals property has a multiline value, we strongly recommend that you use svn propedit instead of svn propset.

Subversion releases prior to 1.5 honor an externals definition format that is a multiline table of subdirectories (relative to the versioned directory on which the property is set), optional revision flags, and fully qualified, absolute Subversion repository URLs. An example of this might looks as follows:

$ svn propget svn:externals calc
third-party/sounds             http://svn.example.com/repos/sounds
third-party/skins -r148        http://svn.example.com/skinproj
third-party/skins/toolkit -r21 http://svn.example.com/skin-maker

When someone checks out a working copy of the calc directory referred to in the previous example, Subversion also continues to check out the items found in its externals definition.

$ svn checkout http://svn.example.com/repos/calc
A  calc
A  calc/Makefile
A  calc/integer.c
A  calc/button.c
Checked out revision 148.

Fetching external item into calc/third-party/sounds
A  calc/third-party/sounds/ding.ogg
A  calc/third-party/sounds/dong.ogg
A  calc/third-party/sounds/clang.ogg
…
A  calc/third-party/sounds/bang.ogg
A  calc/third-party/sounds/twang.ogg
Checked out revision 14.

Fetching external item into calc/third-party/skins
…

As of Subversion 1.5, though, a new format of the svn:externals property is supported. Externals definitions are still multiline, but the order and format of the various pieces of information have changed. The new syntax more closely mimics the order of arguments you might pass to svn checkout: the optional revision flags come first, then the external Subversion repository URL, and finally the relative local subdirectory. Notice, though, that this time we didn't say fully qualified, absolute Subversion repository URLs. That's because the new format supports relative URLs and URLs that carry peg revisions. The previous example of an externals definition might, in Subversion 1.5, look like the following:

$ svn propget svn:externals calc
      http://svn.example.com/repos/sounds third-party/sounds
-r148 http://svn.example.com/skinproj third-party/skins
-r21  http://svn.example.com/skin-maker third-party/skins/toolkit

Or, making use of the peg revision syntax (which we describe in detail in „Peg and Operative Revisions“), it might appear as:

$ svn propget svn:externals calc
http://svn.example.com/repos/sounds third-party/sounds
http://svn.example.com/skinproj@148 third-party/skins
http://svn.example.com/skin-maker@21 third-party/skins/toolkit
[Tipp]Tipp

You should seriously consider using explicit revision numbers in all of your externals definitions. Doing so means that you get to decide when to pull down a different snapshot of external information, and exactly which snapshot to pull. Besides avoiding the surprise of getting changes to third-party repositories that you might not have any control over, using explicit revision numbers also means that as you backdate your working copy to a previous revision, your externals definitions will also revert to the way they looked in that previous revision, which in turn means that the external working copies will be updated to match the way they looked back when your repository was at that previous revision. For software projects, this could be the difference between a successful and a failed build of an older snapshot of your complex codebase.

For most repositories, these three ways of formatting the externals definitions have the same ultimate effect. They all bring the same benefits. Unfortunately, they all bring the same annoyances, too. Since the definitions shown use absolute URLs, moving or copying a directory to which they are attached will not affect what gets checked out as an external (though the relative local target subdirectory will, of course, move with the renamed directory). This can be confusing—even frustrating—in certain situations. For example, say you have a top-level directory named my-project, and you've created an externals definition on one of its subdirectories (my-project/some-dir) that tracks the latest revision of another of its subdirectories (my-project/external-dir).

$ svn checkout http://svn.example.com/projects .
A    my-project
A    my-project/some-dir
A    my-project/external-dir
…
Fetching external item into 'my-project/some-dir/subdir'
Checked out external at revision 11.

Checked out revision 11.
$ svn propget svn:externals my-project/some-dir
subdir http://svn.example.com/projects/my-project/external-dir

$

Now you use svn move to rename the my-project directory. At this point, your externals definition will still refer to a path under the my-project directory, even though that directory no longer exists.

$ svn move -q my-project renamed-project
$ svn commit -m "Rename my-project to renamed-project."
Deleting       my-project
Adding         renamed-project

Committed revision 12.
$ svn update

Fetching external item into 'renamed-project/some-dir/subdir'
svn: Target path does not exist
$

Also, absolute URLs can cause problems with repositories that are available via multiple URL schemes. For example, if your Subversion server is configured to allow everyone to check out the repository over http:// or https://, but only allow commits to come in via https://, you have an interesting problem on your hands. If your externals definitions use the http:// form of the repository URLs, you won't be able to commit anything from the working copies created by those externals. On the other hand, if they use the https:// form of the URLs, anyone who might be checking out via http:// because his client doesn't support https:// will be unable to fetch the external items. Be aware, too, that if you need to reparent your working copy (using svn switch with the --relocate option), externals definitions will not also be reparented.

Subversion 1.5 takes a huge step in relieving these frustrations. As mentioned earlier, the URLs used in the new externals definition format can be relative, and Subversion provides syntax magic for specifying multiple flavors of URL relativity.

../

Relative to the URL of the directory on which the svn:externals property is set

^/

Relative to the root of the repository in which the svn:externals property is versioned

//

Relative to the scheme of the URL of the directory on which the svn:externals property is set

/

Relative to the root URL of the server on which the svn:externals property is versioned

So, looking a fourth time at our previous externals definition example, and making use of the new absolute URL syntax in various ways, we might now see:

$ svn propget svn:externals calc
^/sounds third-party/sounds
/skinproj@148 third-party/skins
//svn.example.com/skin-maker@21 third-party/skins/toolkit

The support that exists for externals definitions in Subversion remains less than ideal, though. An externals definition can point only to directories, not to files. Also, the local subdirectory part of the definition cannot contain .. parent directory indicators (such as ../../skins/myskin). Perhap most disappointingly, the working copies created via the externals definition support are still disconnected from the primary working copy (on whose versioned directories the svn:externals property was actually set). And Subversion still truly operates only on nondisjoint working copies. So, for example, if you want to commit changes that you've made in one or more of those external working copies, you must run svn commit explicitly on those working copies—committing on the primary working copy will not recurse into any external ones.

We've already mentioned some of the additional shortcomings of the old svn:externals format and how the new Subversion 1.5 format improves upon it. But be careful when making use of the new format that you don't inadvertently cause problems for other folks accessing your repository who are using older Subversion clients. While Subversion 1.5 clients will continue to recognize and support the original externals definition format, older clients will not be able to correctly parse the new format.

Besides the svn checkout, svn update, svn switch, and svn export commands which actually manage the disjoint (or disconnected) subdirectories into which externals are checked out, the svn status command also recognizes externals definitions. It displays a status code of X for the disjoint external subdirectories, and then recurses into those subdirectories to display the status of the external items themselves. You can pass the --ignore-externals option to any of these subcommands to disable externals definition processing.

Peg and Operative Revisions

We copy, move, rename, and completely replace files and directories on our computers all the time. And your version control system shouldn't get in the way of your doing these things with your version-controlled files and directories, either. Subversion's file management support is quite liberating, affording almost as much flexibility for versioned files as you'd expect when manipulating your unversioned ones. But that flexibility means that across the lifetime of your repository, a given versioned object might have many paths, and a given path might represent several entirely different versioned objects. This introduces a certain level of complexity to your interactions with those paths and objects.

Subversion is pretty smart about noticing when an object's version history includes such changes of address. For example, if you ask for the revision history log of a particular file that was renamed last week, Subversion happily provides all those logs—the revision in which the rename itself happened, plus the logs of relevant revisions both before and after that rename. So, most of the time, you don't even have to think about such things. But occasionally, Subversion needs your help to clear up ambiguities.

The simplest example of this occurs when a directory or file is deleted from version control, and then a new directory or file is created with the same name and added to version control. The thing you deleted and the thing you later added aren't the same thing. They merely happen to have had the same path—/trunk/object, for example. What, then, does it mean to ask Subversion about the history of /trunk/object? Are you asking about the thing currently at that location, or the old thing you deleted from that location? Are you asking about the operations that have happened to all the objects that have ever lived at that path? Subversion needs a hint about what you really want.

And thanks to moves, versioned object history can get far more twisted than even that. For example, you might have a directory named concept, containing some nascent software project you've been toying with. Eventually, though, that project matures to the point that the idea seems to actually have some wings, so you do the unthinkable and decide to give the project a name. [17] Let's say you called your software Frabnaggilywort. At this point, it makes sense to rename the directory to reflect the project's new name, so concept is renamed to frabnaggilywort. Life goes on, Frabnaggilywort releases a 1.0 version and is downloaded and used daily by hordes of people aiming to improve their lives.

It's a nice story, really, but it doesn't end there. Entrepreneur that you are, you've already got another think in the tank. So you make a new directory, concept, and the cycle begins again. In fact, the cycle begins again many times over the years, each time starting with that old concept directory, then sometimes seeing that directory renamed as the idea cures, sometimes seeing it deleted when you scrap the idea. Or, to get really sick, maybe you rename concept to something else for a while, but later rename the thing back to concept for some reason.

In scenarios like these, attempting to instruct Subversion to work with these reused paths can be a little like instructing a motorist in Chicago's West Suburbs to drive east down Roosevelt Road and turn left onto Main Street. In a mere 20 minutes, you can cross Main Street in Wheaton, Glen Ellyn, and Lombard. And no, they aren't the same street. Our motorist—and our Subversion—need a little more detail to do the right thing.

In version 1.1, Subversion introduced a way for you to tell it exactly which Main Street you meant. It's called the peg revision, and it is provided to Subversion for the sole purpose of identifying a unique line of history. Because at most, one versioned object may occupy a path at any given time—or, more precisely, in any one revision—the combination of a path and a peg revision is all that is needed to refer to a specific line of history. Peg revisions are specified to the Subversion command-line client using at syntax, so called because the syntax involves appending an at sign (@) and the peg revision to the end of the path with which the revision is associated.

But what of the --revision (-r) of which we've spoken so much in this book? That revision (or set of revisions) is called the operative revision (or operative revision range). Once a particular line of history has been identified using a path and peg revision, Subversion performs the requested operation using the operative revision(s). To map this to our Chicagoland streets analogy, if we are told to go to 606 N. Main Street in Wheaton, [18] we can think of Main Street as our path and Wheaton as our peg revision. These two pieces of information identify a unique path that can be traveled (north or south on Main Street), and they keep us from traveling up and down the wrong Main Street in search of our destination. Now we throw in 606 N. as our operative revision of sorts, and we know exactly where to go.

Say that long ago we created our repository, and in revision 1 we added our first concept directory, plus an IDEA file in that directory talking about the concept. After several revisions in which real code was added and tweaked, we, in revision 20, renamed this directory to frabnaggilywort. By revision 27, we had a new concept, a new concept directory to hold it, and a new IDEA file to describe it. And then five years and thousands of revisions flew by, just like they would in any good romance story.

Now, years later, we wonder what the IDEA file looked like back in revision 1. But Subversion needs to know whether we are asking about how the current file looked back in revision 1, or whether we are asking for the contents of whatever file lived at concepts/IDEA in revision 1. Certainly those questions have different answers, and because of peg revisions, you can ask those questions. To find out how the current IDEA file looked in that old revision, you run:

$ svn cat -r 1 concept/IDEA 
svn: Unable to find repository location for 'concept/IDEA' in revision 1

Of course, in this example, the current IDEA file didn't exist yet in revision 1, so Subversion gives an error. The previous command is shorthand for a longer notation which explicitly lists a peg revision. The expanded notation is:

$ svn cat -r 1 concept/IDEA@BASE
svn: Unable to find repository location for 'concept/IDEA' in revision 1

And when executed, it has the expected results.

The perceptive reader is probably wondering at this point whether the peg revision syntax causes problems for working copy paths or URLs that actually have at signs in them. After all, how does svn know whether news@11 is the name of a directory in my tree or just a syntax for revision 11 of news? Thankfully, while svn will always assume the latter, there is a trivial workaround. You need only append an at sign to the end of the path, such as news@11@. svn cares only about the last at sign in the argument, and it is not considered illegal to omit a literal peg revision specifier after that at sign. This workaround even applies to paths that end in an at sign—you would use filename@@ to talk about a file named filename@.

Let's ask the other question, then—in revision 1, what were the contents of whatever file occupied the address concepts/IDEA at the time? We'll use an explicit peg revision to help us out.

$ svn cat concept/IDEA@1
The idea behind this project is to come up with a piece of software
that can frab a naggily wort.  Frabbing naggily worts is tricky
business, and doing it incorrectly can have serious ramifications, so
we need to employ over-the-top input validation and data verification
mechanisms.

Notice that we didn't provide an operative revision this time. That's because when no operative revision is specified, Subversion assumes a default operative revision that's the same as the peg revision.

As you can see, the output from our operation appears to be correct. The text even mentions frabbing naggily worts, so this is almost certainly the file that describes the software now called Frabnaggilywort. In fact, we can verify this using the combination of an explicit peg revision and explicit operative revision. We know that in HEAD, the Frabnaggilywort project is located in the frabnaggilywort directory. So we specify that we want to see how the line of history identified in HEAD as the path frabnaggilywort/IDEA looked in revision 1.

$ svn cat -r 1 frabnaggilywort/IDEA@HEAD
The idea behind this project is to come up with a piece of software
that can frab a naggily wort.  Frabbing naggily worts is tricky
business, and doing it incorrectly can have serious ramifications, so
we need to employ over-the-top input validation and data verification
mechanisms.

And the peg and operative revisions need not be so trivial, either. For example, say frabnaggilywort had been deleted from HEAD, but we know it existed in revision 20, and we want to see the diffs for its IDEA file between revisions 4 and 10. We can use the peg revision 20 in conjunction with the URL that would have held Frabnaggilywort's IDEA file in revision 20, and then use 4 and 10 as our operative revision range.

$ svn diff -r 4:10 http://svn.red-bean.com/projects/frabnaggilywort/IDEA@20
Index: frabnaggilywort/IDEA
===================================================================
--- frabnaggilywort/IDEA	(revision 4)
+++ frabnaggilywort/IDEA	(revision 10)
@@ -1,5 +1,5 @@
-The idea behind this project is to come up with a piece of software
-that can frab a naggily wort.  Frabbing naggily worts is tricky
-business, and doing it incorrectly can have serious ramifications, so
-we need to employ over-the-top input validation and data verification
-mechanisms.
+The idea behind this project is to come up with a piece of
+client-server software that can remotely frab a naggily wort.
+Frabbing naggily worts is tricky business, and doing it incorrectly
+can have serious ramifications, so we need to employ over-the-top
+input validation and data verification mechanisms.

Fortunately, most folks aren't faced with such complex situations. But when you are, remember that peg revisions are that extra hint Subversion needs to clear up ambiguity.

Changelists

It is commonplace for a developer to find himself working at any given time on multiple different, distinct changes to a particular bit of source code. This isn't necessarily due to poor planning or some form of digital masochism. A software engineer often spots bugs in his peripheral vision while working on some nearby chunk of source code. Or perhaps he's halfway through some large change when he realizes the solution he's working on is best committed as several smaller logical units. Often, these logical units aren't nicely contained in some module, safely separated from other changes. The units might overlap, modifying different files in the same module, or even modifying different lines in the same file.

Developers can employ various work methodologies to keep these logical changes organized. Some use separate working copies of the same repository to hold each individual change in progress. Others might choose to create short-lived feature branches in the repository and use a single working copy that is constantly switched to point to one such branch or another. Still others use diff and patch tools to back up and restore uncommitted changes to and from patch files associated with each change. Each of these methods has its pros and cons, and to a large degree, the details of the changes being made heavily influence the methodology used to distinguish them.

Subversion 1.5 brings a new changelists feature that adds yet another method to the mix. Changelists are basically arbitrary labels (currently at most one per file) applied to working copy files for the express purpose of associating multiple files together. Users of many of Google's software offerings are familiar with this concept already. For example, Gmail doesn't provide the traditional folders-based email organization mechanism. In Gmail, you apply arbitrary labels to emails, and multiple emails can be said to be part of the same group if they happen to share a particular label. Viewing only a group of similarly labeled emails then becomes a simple user interface trick. Many other Web 2.0 sites have similar mechanisms—consider the tags used by sites such as YouTube and Flickr, categories applied to blog posts, and so on. Folks understand today that organization of data is critical, but that how that data is organized needs to be a flexible concept. The old files-and-folders paradigm is too rigid for some applications.

Subversion's changelist support allows you to create changelists by applying labels to files you want to be associated with that changelist, remove those labels, and limit the scope of the files on which its subcommands operate to only those bearing a particular label. In this section, we'll look in detail at how to do these things.

Creating and Modifying Changelists

You can create, modify, and delete changelists using the svn changelist command. More accurately, you use this command to set or unset the changelist association of a particular working copy file. A changelist is effectively created the first time you label a file with that changelist; it is deleted when you remove that label from the last file that had it. Let's examine a usage scenario that demonstrates these concepts.

Harry is fixing some bugs in the calculator application's mathematics logic. His work leads him to change a couple of files:

$ svn status
M      integer.c
M      mathops.c
$

While testing his bug fix, Harry notices that his changes bring to light a tangentially related bug in the user interface logic found in button.c. Harry decides that he'll go ahead and fix that bug, too, as a separate commit from his math fixes. Now, in a small working copy with only a handful of files and few logical changes, Harry can probably keep his two logical change groupings mentally organized without any problem. But today he's going to use Subversion's changelists feature as a special favor to the authors of this book.

Harry first creates a changelist and associates with it the two files he's already changed. He does this by using the svn changelist command to assign the same arbitrary changelist name to those files:

$ svn changelist math-fixes integer.c mathops.c
Path 'integer.c' is now a member of changelist 'math-fixes'.
Path 'mathops.c' is now a member of changelist 'math-fixes'.
$ svn status

--- Changelist 'math-fixes':
M      integer.c
M      mathops.c
$

As you can see, the output of svn status reflects this new grouping.

Harry now sets off to fix the secondary UI problem. Since he knows which file he'll be changing, he assigns that path to a changelist, too. Unfortunately, Harry carelessly assigns this third file to the same changelist as the previous two files:

$ svn changelist math-fixes button.c
Path 'button.c' is now a member of changelist 'math-fixes'.
$ svn status

--- Changelist 'math-fixes':
       button.c
M      integer.c
M      mathops.c
$

Fortunately, Harry catches his mistake. At this point, he has two options. He can remove the changelist association from button.c, and then assign a different changelist name:

$ svn changelist --remove button.c
Path 'button.c' is no longer a member of a changelist.
$ svn changelist ui-fix button.c
Path 'button.c' is now a member of changelist 'ui-fix'.
$

Or, he can skip the removal and just assign a new changelist name. In this case, Subversion will first warn Harry that button.c is being removed from the first changelist:

$ svn changelist ui-fix button.c
svn: warning: Removing 'button.c' from changelist 'math-fixes'.
Path 'button.c' is now a member of changelist 'ui-fix'.
$ svn status

--- Changelist 'ui-fix':
       button.c

--- Changelist 'math-fixes':
M      integer.c
M      mathops.c
$

Harry now has two distinct changelists present in his working copy, and svn status will group its output according to these changelist determinations. Notice that even though Harry hasn't yet modified button.c, it still shows up in the output of svn status as interesting because it has a changelist assignment. Changelists can be added to and removed from files at any time, regardless of whether they contain local modifications.

Harry now fixes the user interface problem in button.c.

$ svn status

--- Changelist 'ui-fix':
M      button.c

--- Changelist 'math-fixes':
M      integer.c
M      mathops.c
$

Changelists As Operation Filters

The visual grouping that Harry sees in the output of svn status as shown in our previous section is nice, but not entirely useful. The status command is but one of many operations that he might wish to perform on his working copy. Fortunately, many of Subversion's other operations understand how to operate on changelists via the use of the --changelist option.

When provided with a --changelist option, Subversion commands will limit the scope of their operation to only those files to which a particular changelist name is assigned. If Harry now wants to see the actual changes he's made to the files in his math-fixes changelist, he could explicitly list only the files that make up that changelist on the svn diff command line.

$ svn diff integer.c mathops.c
Index: integer.c
===================================================================
--- integer.c	(revision 1157)
+++ integer.c	(working copy)
…
Index: mathops.c
===================================================================
--- mathops.c	(revision 1157)
+++ mathops.c	(working copy)
…
$

That works okay for a few files, but what if Harry's change touched 20 or 30 files? That would be an annoyingly long list of explicitly named files. Now that he's using changelists, though, Harry can avoid explicitly listing the set of files in his changelist from now on, and instead provide just the changelist name:

$ svn diff --changelist math-fixes
Index: integer.c
===================================================================
--- integer.c	(revision 1157)
+++ integer.c	(working copy)
…
Index: mathops.c
===================================================================
--- mathops.c	(revision 1157)
+++ mathops.c	(working copy)
…
$

And when it's time to commit, Harry can again use the --changelist option to limit the scope of the commit to files in a certain changelist. He might commit his user interface fix by doing the following:

$ svn ci -m "Fix a UI bug found while working on math logic." \
      --changelist ui-fix
Sending        button.c
Transmitting file data .
Committed revision 1158.
$

In fact, the svn commit command provides a second changelists-related option: --keep-changelists. Normally, changelist assignments are removed from files after they are committed. But if --keep-changelists is provided, Subversion will leave the changelist assignment on the committed (and now unmodified) files. In any case, committing files assigned to one changelist leaves other changelists undisturbed.

$ svn status

--- Changelist 'math-fixes':
M      integer.c
M      mathops.c
$
[Anmerkung]Anmerkung

The --changelist option acts only as a filter for Subversion command targets, and will not add targets to an operation. For example, on a commit operation specified as svn commit /path/to/dir, the target is the directory /path/to/dir and its children (to infinite depth). If you then add a changelist specifier to that command, only those files in and under /path/to/dir that are assigned that changelist name will be considered as targets of the commit—the commit will not include files located elsewhere (such is in /path/to/another-dir), regardless of their changelist assignment, even if they are part of the same working copy as the operation's target(s).

Even the svn changelist command accepts the --changelist option. This allows you to quickly and easily rename or remove a changelist:

$ svn changelist math-bugs --changelist math-fixes --depth infinity .
svn: warning: Removing 'integer.c' from changelist 'math-fixes'.
Path 'integer.c' is now a member of changelist 'math-bugs'.
svn: warning: Removing 'mathops.c' from changelist 'math-fixes'.
Path 'mathops.c' is now a member of changelist 'math-bugs'.
$ svn changelist --remove --changelist math-bugs --depth infinity .
Path 'integer.c' is no longer a member of a changelist.
Path 'mathops.c' is no longer a member of a changelist.
$

Finally, you can specify multiple instances of the --changelist option on a single command line. Doing so limits the operation you are performing to files found in any of the specified changesets.

Changelist Limitations

Subversion's changelist feature is a handy tool for grouping working copy files, but it does have a few limitations. Changelists are artifacts of a particular working copy, which means that changelist assignments cannot be propagated to the repository or otherwise shared with other users. Changelists can be assigned only to files—Subversion doesn't currently support the use of changelists with directories. Finally, you can have at most one changelist assignment on a given working copy file. Here is where the blog post category and photo service tag analogies break down—if you find yourself needing to assign a file to multiple changelists, you're out of luck.

Network Model

At some point, you're going to need to understand how your Subversion client communicates with its server. Subversion's networking layer is abstracted, meaning that Subversion clients exhibit the same general behaviors no matter what sort of server they are operating against. Whether speaking the HTTP protocol (http://) with the Apache HTTP Server or speaking the custom Subversion protocol (svn://) with svnserve, the basic network model is the same. In this section, we'll explain the basics of that network model, including how Subversion manages authentication and authorization matters.

Requests and Responses

The Subversion client spends most of its time managing working copies. When it needs information from a remote repository, however, it makes a network request, and the server responds with an appropriate answer. The details of the network protocol are hidden from the user—the client attempts to access a URL, and depending on the URL scheme, a particular protocol is used to contact the server (see the sidebar Repository URLs).

[Tipp]Tipp

Run svn --version to see which URL schemes and protocols the client knows how to use.

When the server process receives a client request, it often demands that the client identify itself. It issues an authentication challenge to the client, and the client responds by providing credentials back to the server. Once authentication is complete, the server responds with the original information that the client asked for. Notice that this system is different from systems such as CVS, where the client preemptively offers credentials (logs in) to the server before ever making a request. In Subversion, the server pulls credentials by challenging the client at the appropriate moment, rather than the client pushing them. This makes certain operations more elegant. For example, if a server is configured to allow anyone in the world to read a repository, the server will never issue an authentication challenge when a client attempts to svn checkout.

If the particular network requests issued by the client result in a new revision being created in the repository (e.g., svn commit), Subversion uses the authenticated username associated with those requests as the author of the revision. That is, the authenticated user's name is stored as the value of the svn:author property on the new revision (see „Subversion-Propertys“). If the client was not authenticated (i.e., if the server never issued an authentication challenge), the revision's svn:author property is empty.

Client Credentials Caching

Many servers are configured to require authentication on every request. This would be a big annoyance to users if they were forced to type their passwords over and over again. Fortunately, the Subversion client has a remedy for this—a built-in system for caching authentication credentials on disk. By default, whenever the command-line client successfully responds to a server's authentication challenge, it saves the credentials in the user's private runtime configuration area (~/.subversion/auth/ on Unix-like systems or %APPDATA%/Subversion/auth/ on Windows; see „Laufzeit-Konfigurationsbereich“ for more details about the runtime configuration system). Successful credentials are cached on disk and keyed on a combination of the server's hostname, port, and authentication realm.

When the client receives an authentication challenge, it first looks for the appropriate credentials in the user's disk cache. If seemingly suitable credentials are not present, or if the cached credentials ultimately fail to authenticate, the client will, by default, fall back to prompting the user for the necessary information.

The security-conscious reader will suspect immediately that there is reason for concern here. Caching passwords on disk? That's terrible! You should never do that!

The Subversion developers recognize the legitimacy of such concerns, and so Subversion works with available mechanisms provided by the operating system and environment to try to minimize the risk of leaking this information. Here's a breakdown of what this means for users on the most common platforms:

  • On Windows 2000 and later, the Subversion client uses standard Windows cryptography services to encrypt the password on disk. Because the encryption key is managed by Windows and is tied to the user's own login credentials, only the user can decrypt the cached password. (Note that if the user's Windows account password is reset by an administrator, all of the cached passwords become undecipherable. The Subversion client will behave as though they don't exist, prompting for passwords when required.)

  • Similarly, on Mac OS X, the Subversion client stores all repository passwords in the login keyring (managed by the Keychain service), which is protected by the user's account password. User preference settings can impose additional policies, such as requiring that the user's account password be entered each time the Subversion password is used.

  • For other Unix-like operating systems, no standard keychain services exist. However, the auth/ caching area is still permission-protected so that only the user (owner) can read data from it, not the world at large. The operating system's own file permissions protect the passwords.

Of course, for the truly paranoid, none of these mechanisms meets the test of perfection. So for those folks willing to sacrifice convenience for the ultimate in security, Subversion provides various ways of disabling its credentials caching system altogether.

To disable caching for a single command, pass the --no-auth-cache option:

$ svn commit -F log_msg.txt --no-auth-cache
Authentication realm: <svn://host.example.com:3690> example realm
Username:  joe
Password for 'joe':

Adding         newfile
Transmitting file data .
Committed revision 2324.

# password was not cached, so a second commit still prompts us

$ svn delete newfile
$ svn commit -F new_msg.txt
Authentication realm: <svn://host.example.com:3690> example realm
Username:  joe
…

Or, if you want to disable credential caching permanently, you can edit the config file in your runtime configuration area and set the store-auth-creds option to no. This will prevent the storing of credentials used in any Subversion interactions you perform on the affected computer. This can be extended to cover all users on the computer, too, by modifying the system-wide runtime configuration area (described in „Aufbau des Konfigurationsbereichs“).

[auth]
store-auth-creds = no

Sometimes users will want to remove specific credentials from the disk cache. To do this, you need to navigate into the auth/ area and manually delete the appropriate cache file. Credentials are cached in individual files; if you look inside each file, you will see keys and values. The svn:realmstring key describes the particular server realm that the file is associated with:

$ ls ~/.subversion/auth/svn.simple/
5671adf2865e267db74f09ba6f872c28
3893ed123b39500bca8a0b382839198e
5c3c22968347b390f349ff340196ed39

$ cat ~/.subversion/auth/svn.simple/5671adf2865e267db74f09ba6f872c28

K 8
username
V 3
joe
K 8
password
V 4
blah
K 15
svn:realmstring
V 45
<https://svn.domain.com:443> Joe's repository
END

Once you have located the proper cache file, just delete it.

One last word about svn's authentication behavior, specifically regarding the --username and --password options. Many client subcommands accept these options, but it is important to understand that using these options does not automatically send credentials to the server. As discussed earlier, the server pulls credentials from the client when it deems necessary; the client cannot push them at will. If a username and/or password are passed as options, they will be presented to the server only if the server requests them. These options are typically used to authenticate as a different user than Subversion would have chosen by default (such as your system login name) or when trying to avoid interactive prompting (such as when calling svn from a script).

[Anmerkung]Anmerkung

A common mistake is to misconfigure a server so that it never issues an authentication challenge. When users pass --username and --password options to the client, they're surprised to see that they're never used; that is, new revisions still appear to have been committed anonymously!

Here is a final summary that describes how a Subversion client behaves when it receives an authentication challenge.

  1. First, the client checks whether the user specified any credentials as command-line options (--username and/or --password). If so, the client will try to use those credentials to authenticate against the server.

  2. If no command-line credentials were provided, or the provided ones were invalid, the client looks up the server's hostname, port, and realm in the runtime configuration's auth/ area, to see whether appropriate credentials are cached there. If so, it attempts to use those credentials to authenticate.

  3. Finally, if the previous mechanisms failed to successfully authenticate the user against the server, the client resorts to interactively prompting the user for valid credentials (unless instructed not to do so via the --non-interactive option or its client-specific equivalents).

If the client successfully authenticates by any of these methods, it will attempt to cache the credentials on disk (unless the user has disabled this behavior, as mentioned earlier).

Summary

After reading this chapter, you should have a firm grasp on some of Subversion's features that, while perhaps not used every time you interact with your version control system, are certainly handy to know about. But don't stop here! Read on to the following chapter, where you'll learn about branches, tags, and merging. Then you'll have nearly full mastery of the Subversion client. Though our lawyers won't allow us to promise you anything, this additional knowledge could make you measurably more cool. [19]




[8] If you're familiar with XML, this is pretty much the ASCII subset of the syntax for XML "Name".

[9] Fixing spelling errors, grammatical gotchas, and just-plain-wrongness in commit log messages is perhaps the most common use case for the --revprop option.

[10] You think that was rough? During that same era, WordPerfect also used .DOC for their proprietary file format's preferred extension!

[11] The Windows filesystems use file extensions (such as .EXE, .BAT, and .COM) to denote executable files.

[12] Isn't that the whole point of a build system?

[13] … or maybe even a section of a book …

[14] Communication wouldn't have been such bad medicine for Harry and Sally's Hollywood namesakes, either, for that matter.

[15] Subversion does not currently allow locks on directories.

[16] Except, perhaps, a classic Vulcan mind-meld.

[17] You're not supposed to name it. Once you name it, you start getting attached to it.—Mike Wazowski

[18] 606 N. Main Street, Wheaton, Illinois, is the home of the Wheaton History Center. It seemed appropriate….

[19] No purchase necessary. Certains terms and conditions apply. No guarantee of coolness—implicit or otherwise—exists. Mileage may vary.

Kapitel 4. Verzweigen und Zusammenführen

 

君子务本 (Der Edle pflegt die Wurzel)

 
 --Konfuzius

Verzweigen (Branching), Etikettieren (Tagging) und Zusammenführen (Merging) sind Konzepte, die fast allen Versionskontrollsystemen gemein sind. Falls Sie mit diesen Begriffen nicht vertraut sein sollten, geben wir in diesem Kapitel eine gute Einführung. Falls Sie damit vertraut sind, werden Sie es hoffentlich interessant finden, zu sehen, wie Subversion diese Konzepte implementiert.

Verzweigen ist ein grundlegender Teil der Versionskontrolle. Falls Sie Subversion erlauben wollen, Ihre Daten zu verwalten, ist dies eine Fähigkeit, von der Sie letztendlich abhängig sein werden. Dieses Kapitel geht davon aus, dass Sie mit den grundlegenden Konzepten von Subversion vertraut sind (Kapitel 1, Grundlegende Konzepte).

Was ist ein Zweig?

Angenommen, Ihre Aufgabe ist es, ein Dokument für eine Abteilung Ihrer Firma zu pflegen – eine Art Handbuch. Eines Tages fragt eine andere Abteilung nach dem gleichen Handbuch, jedoch an einigen Stellen für ihre Bedürfnisse abgewandelt, da sie auf etwas andere Weise arbeiten.

Was machen Sie in dieser Situation? Sie machen das Offensichtliche: Sie erstellen eine Kopie Ihres Dokumentes und beginnen, die beiden Kopien getrennt zu pflegen. Sobald Sie irgendeine Abteilung auffordert, kleine Änderungen vorzunehmen, pflegen Sie diese in die eine oder andere Kopie ein.

Oftmals möchten Sie die selbe Änderung in beiden Kopien machen. Wenn Sie zum Beispiel einen Schreibfehler in der ersten Kopie entdecken, ist es sehr wahrscheinlich, dass dieser Fehler auch in der zweiten Kopie vorliegt. Schließlich sind die beiden Dokumente fast gleich; sie unterscheiden sich nur in kleinen Dingen.

Das ist das Grundkonzept eines Zweigs (Branch) – nämlich eine Entwicklungslinie, die unabhängig von einer anderen existiert, jedoch über eine gemeinsame Geschichte verfügt, wenn lang genug in der Zeit zurück gegangen wird. Ein Zweig beginnt sein Leben stets als eine Kopie von etwas und läuft von da an weiter, wobei er seine eigene Geschichte erzeugt (siehe Abbildung 4.1, „Entwicklungszweige“).

Abbildung 4.1. Entwicklungszweige

Entwicklungszweige


Subversion verfügt über Befehle, die Ihnen helfen, parallele Zweige Ihrer Dateien und Verzeichnisse zu verwalten. Es erlaubt Ihnen, durch das Kopieren Ihrer Daten, Zweige zu erstellen und merkt sich, dass die Zweige untereinander in Beziehung stehen. Es hilft Ihnen auch, Änderungen von einem Zweig auf den anderen zu duplizieren. Schließlich ermöglicht es, dass Teile Ihrer Arbeitskopie verschiedene Zweige repräsentieren können, was Ihnen während Ihrer täglichen Arbeit erlaubt, verschiedene Entwicklungslinien zu mischen und gegenüberzustellen.

Verwenden von Zweigen

An dieser Stelle sollten Sie verstehen, wie jede Übergabe an das Repository dort einen völlig neuen Dateibaum (Revision genannt) erzeugt. Wenn nicht, blättern Sie zurück und lesen Sie in „Revisionen“ über Revisionen nach.

Für dieses Kapitel verwenden wir das Beispiel aus Kapitel 1, Grundlegende Konzepte. Erinnern Sie sich, dass Sie und Ihre Mitarbeiterin Sally sich ein Repository teilen, das zwei Projekte beinhaltet: paint und calc. Beachten Sie, dass in Abbildung 4.2, „Repository-Struktur zu Beginn“ dieses Mal jedoch jedes Projektverzeichnis Unterverzeichnisse namens trunk und branches beinhaltet. Der Grund hierfür wird bald klar sein.

Abbildung 4.2. Repository-Struktur zu Beginn

Repository-Struktur zu Beginn


Wie vorher sei hier angenommen, dass sowohl Sally als auch Sie Arbeitskopien des calc Projektes besitzen. Ausdrücklich hat jeder von Ihnen eine Arbeitskopie von /calc/trunk. Alle Dateien des Projektes befinden sich in diesem Unterverzeichnis statt in /calc selber, da Ihr Team entschieden hat, dass in /calc/trunk die Hauptlinie der Entwicklung stattfindet.

Sagen wir mal, dass Sie die Aufgabe bekommen haben, ein großes Stück Software umzusetzen. Die Erstellung benötigt eine lange Zeit und berührt alle Dateien im Projekt. Das Problem, dass sofort auftaucht ist, dass Sie nicht Sally in die Quere kommen möchten, die gerade hier und da kleinere Fehler beseitigt. Sie ist abhängig von der Tatsache, dass die letzte Version des Projektes (in /calc/trunk) stets benutzbar ist. Wenn Sie nun damit beginnen, Stück für Stück Ihre Änderungen zu übergeben, werden Sie gewiss die Dinge für Sally (und auch für andere Teammitglieder) in Unordnung bringen.

Eine Strategie ist, sich in ein Loch zu verkriechen: Sie und Sally können für eine Woche oder zwei den Informationsaustausch einstellen. Das heißt, Sie fangen damit an, die Dateien Ihrer Arbeitskopie auszuräumen und umzuorganisieren, ohne Änderungen zu übergeben oder die Arbeitskopie zu aktualisieren, bevor Sie mit Ihrer Arbeit vollständig fertig sind. Das wirft allerdings einige Probleme auf. Erstens ist das nicht sehr sicher. Viele Leute möchten Ihre Arbeit regelmäßig ins Repository sichern, für den Fall, dass etwas Schlimmes mit der Arbeitskopie passieren könnte. Zweitens ist das nicht sehr flexibel. Falls Sie Ihre Arbeit an mehreren Rechnern verrichten (vielleicht haben Sie eine Arbeitskopie von /calc/trunk auf zwei unterschiedlichen Maschinen), müssten Sie entweder alle Änderungen manuell hin und her kopieren oder die gesamte Arbeit an nur einem Rechner erledigen. Ebenso schwierig wäre es, Ihre Änderungen mit anderen zu teilen. Eine weit verbreitete beste Vorgehensweise ist es, Ihren Mitarbeitern zu erlauben, während Sie mit Ihrer Arbeit fortfahren, Ihre bisherigen Ergebnisse zu überprüfen. Wenn niemand Ihre unmittelbaren Änderungen sieht, haben Sie keine möglichen Rückmeldungen und es könnte sein, dass Sie für Wochen einen falschen Weg einschlagen, bevor es jemand aus Ihrem Team bemerkt. Schließlich könnte es am Ende, wenn Sie mit Ihren Änderungen fertig sind, sehr schwierig sein, Ihr Arbeitsergebnis wieder mit dem Hauptteil der Quelltexte Ihrer Firma zusammenzuführen. Sally (und andere) hätten viele andere Änderungen ins Repository übergeben haben können, die sich schwer in Ihre Arbeitskopie einarbeiten ließen – besonders, falls Sie svn update nach Wochen der Isolierung ausführen.

Die bessere Lösung ist, Ihren eigenen Zweig oder Ihre eigene Entwicklungslinie im Repository zu erzeugen. Dies erlaubt Ihnen, Ihre halbfertigen Arbeitsergebnisse regelmäßig zu sichern, ohne andere zu stören; dennoch können Sie selektiv Informationen mit Ihren Kollegen teilen. Im Weiteren werden Sie sehen, wie das funktioniert.

Erzeugen eines Zweiges

Es ist sehr einfach, einen Zweig zu erzeugen – Sie erstellen mit dem Befehl svn copy eine Kopie des Projektes im Repository. Subversion kann nicht nur Dateien, sondern auch komplette Verzeichnisse kopieren. In diesem Fall möchten Sie eine Kopie des Verzeichnisses /calc/trunk machen. Wo soll die neue Kopie angelegt werden? Wo Sie wünschen – es ist eine Frage der Projektkonventionen. Sagen wir mal, dass Ihr Team die Konvention vereinbart hat, Zweige im Bereich /calc/branches des Repositorys anzulegen, und Sie Ihren Zweig my-calc-branch nennen möchten. Sie werden ein neues Verzeichnis /calc/branches/my-calc-branch anlegen, das als Kopie von /calc/trunk beginnt.

Sie haben vielleicht schon gesehen, wie mit svn copy in einer Arbeitskopie eine Datei auf eine andere kopiert wird. Es kann allerdings auch verwendet werden, um eine entfernte Kopie innerhalb des Repositorys durchzuführen. Kopieren Sie einfach einen URL auf einen anderen:

$ svn copy http://svn.example.com/repos/calc/trunk \
           http://svn.example.com/repos/calc/branches/my-calc-branch \
      -m "Privaten Zweig von /calc/trunk angelegt."

Revision 341 übertragen.

Dieser Befehl bewirkt eine fast sofortige Übergabe im Repository, wobei in Revision 341 ein neues Verzeichnis erzeugt wird. Das neue Verzeichnis ist eine Kopie von /calc/trunk. Dies wird in Abbildung 4.3, „Repository mit neuer Kopie“ gezeigt. [20] Obwohl es auch möglich ist, einen Zweig zu erzeugen, indem svn copy verwendet wird, um ein Verzeichnis innerhalb der Arbeitskopie zu duplizieren, wird dieses Vorgehen nicht empfohlen. Es kann in der Tat sehr langsam sein! Das client-seitige Kopieren eines Verzeichnisses besitzt einen linearen Zeitaufwand, da wirklich jede Datei und jedes Verzeichnis auf der lokalen Platte dupliziert werden muss. Das Kopieren eines Verzeichnisses auf dem Server jedoch besitzt einen konstanten Zeitaufwand und ist die Art und Weise, auf die die meisten Leute Zweige erstellen.

Abbildung 4.3. Repository mit neuer Kopie

Repository mit neuer Kopie


Arbeiten mit Ihrem Zweig

Da Sie nun einen Zweig des Projektes erzeugt haben, können Sie eine neue Arbeitskopie auschecken, um ihn zu benutzen:

$ svn checkout http://svn.example.com/repos/calc/branches/my-calc-branch
A  my-calc-branch/Makefile
A  my-calc-branch/integer.c
A  my-calc-branch/button.c
Ausgecheckt, Revision 341.

An dieser Arbeitskopie ist nichts besonders; sie spiegelt bloß ein anderes Verzeichnis im Repository wieder. Wenn Sie Änderungen übergeben, wird sie Sally jedoch nicht sehen, wenn sie aktualisiert, da sie eine Arbeitskopie von /calc/trunk hat. (Stellen Sie sicher, dass Sie „Zweige durchlaufen“ weiter unten in diesem Kapitel lesen: Der Befehl svn switch ist eine Alternative für die Bereitstellung einer Arbeitskopie eines Zweiges.)

Tun wir mal so, als ob eine Woche ins Land geht und die folgenden Übergaben stattfinden:

  • Sie machen eine Änderung an /calc/branches/my-calc-branch/button.c, die die Revision 342 erzeugt.

  • Sie machen eine Änderung an /calc/branches/my-calc-branch/integer.c, die die Revision 343 erzeugt.

  • Sally macht eine Änderung an /calc/trunk/integer.c, die die Revision 344 erzeugt.

Nun finden zwei unabhängige Entwicklungslinien (siehe Abbildung 4.4, „Die Verzweigung der Geschichte einer Datei“) auf integer.c statt.

Abbildung 4.4. Die Verzweigung der Geschichte einer Datei

Die Verzweigung der Geschichte einer Datei


Es wird interessant, wenn Sie die Geschichte der Änderungen an Ihrer Kopie von integer.c betrachten:

$ pwd
/home/user/my-calc-branch

$ svn log -v integer.c
------------------------------------------------------------------------
r343 | user | 2002-11-07 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines
Geänderte Pfade:
   M /calc/branches/my-calc-branch/integer.c

* integer.c:  Wazjub gefrozzelt.

------------------------------------------------------------------------
r341 | user | 2002-11-03 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines
Geänderte Pfade:
   A /calc/branches/my-calc-branch (from /calc/trunk:340)

Privaten Zweig von /calc/trunk angelegt.

------------------------------------------------------------------------
r303 | sally | 2002-10-29 21:14:35 -0600 (Tue, 29 Oct 2002) | 2 lines
Geänderte Pfade:
   M /calc/trunk/integer.c

* integer.c:  Einen Docstring geändert.

------------------------------------------------------------------------
r98 | sally | 2002-02-22 15:35:29 -0600 (Fri, 22 Feb 2002) | 2 lines
Geänderte Pfade:
   A /calc/trunk/integer.c

* integer.c:  Diese Datei dem Projekt hinzugefügt.

------------------------------------------------------------------------

Beachten Sie, dass Subversion die Geschichte von integer.c auf Ihrem Zweig über die gesamte Zeit zurück verfolgt, und dabei sogar über den Punkt hinweg geht, an dem es kopiert wurde. Es zeigt die Erzeugung des Zweigs als ein Ereignis in der Geschichte, da integer.c implizit kopiert wurde, als alles andere in /calc/trunk/ kopiert wurde. Sehen Sie nun, was passiert, wenn Sally den gleichen Befehl auf Ihre Arbeitskopie der Datei anwendet:

$ pwd
/home/sally/calc

$ svn log -v integer.c
------------------------------------------------------------------------
r344 | sally | 2002-11-07 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines
Changed paths:
   M /calc/trunk/integer.c

* integer.c:  fix a bunch of spelling errors.

------------------------------------------------------------------------
r303 | sally | 2002-10-29 21:14:35 -0600 (Tue, 29 Oct 2002) | 2 lines
Changed paths:
   M /calc/trunk/integer.c

* integer.c:  changed a docstring.

------------------------------------------------------------------------
r98 | sally | 2002-02-22 15:35:29 -0600 (Fri, 22 Feb 2002) | 2 lines
Changed paths:
   A /calc/trunk/integer.c

* integer.c:  adding this file to the project.

------------------------------------------------------------------------

Sally sieht ihre eigene Änderung in Revision 344, aber nicht die Änderung, die Sie in Revision 343 gemacht haben. Was Subversion angeht, hatten diese beiden Übergaben Auswirkungen auf unterschiedliche Dateien an unterschiedlichen Repository-Orten. Dennoch zeigt Subversion doch, dass die beiden Dateien einen Teil der Geschichte gemeinsam haben. Bevor die Kopie des Zweiges in Revision 341 gemacht wurde, waren die Dateien dieselbe Datei. Deshalb sehen sowohl Sie als auch Sally die Änderungen, die in den Revisionen 303 und 98 gemacht wurden.

Die Schlüsselkonzepte des Verzweigens

Sie sollten sich zwei Lektionen aus diesem Abschnitt merken. Erstens besitzt Subversion kein internes Konzept für einen Zweig – es weiß lediglich, wie Kopien angelegt werden. Wenn Sie ein Verzeichnis kopieren, ist das entstehende Verzeichnis bloß ein Zweig, weil Sie ihm diese Bedeutung geben. Sie mögen über das Verzeichnis anders denken oder es anders behandeln, doch für Subversion ist es einfach ein gewöhnliches Verzeichnis, das nebenbei mit einigen zusätzlichen historischen Informationen ausgestattet ist.

Zweitens bestehen die Zweige von Subversion, bedingt durch den Kopiermechanismus, als normale Dateisystemverzeichnisse im Repository. Das ist ein Unterschied zu anderen Versionskontrollsystemen, bei denen Zweige typischerweise definiert werden, indem auf einer eigenen Ebene den Dateisammlungen Etiketten hinzugefügt werden. Der Ort Ihres Zweig-Verzeichnisses spielt für Subversion keine Rolle. Die meisten Teams folgen der Konvention, alle Zweige in einem Verzeichnis namens /branches abzulegen, jedoch steht es Ihnen frei, eine Vorgehensweise nach Ihren Wünschen zu erfinden.

Grundlegendes Zusammenführen

Nun arbeiten Sie und Sally auf parallelen Zweigen des Projektes: Sie arbeiten auf einem privaten Zweig, und Sally arbeitet auf dem Stamm oder dem Hauptzweig der Entwicklung.

Bei Projekten mit einer großen Zahl von Mitarbeitern haben die meisten gewöhnlich Arbeitskopien vom Stamm. Sobald jemand eine langwierige Änderung machen muss, die wahrscheinlich den Stamm stören würde, ist die Standardvorgehensweise, einen Zweig zu erzeugen und die Änderungen bis zum Abschluss der Arbeiten nach dorthin zu übergeben.

Die gute Nachricht ist also, dass Sie und Sally sich nicht in die Quere kommen. Die schlechte Nachricht ist, dass es sehr leicht ist, zu weit auseinander zu treiben. Erinnern Sie sich, dass eins der Probleme bei der Strategie sich in ein Loch zu verkriechen war, dass es zu dem Zeitpunkt, an dem Sie mit dem Zweig fertig sind, fast unmöglich sein kann, Ihre Änderungen ohne eine riesige Zahl an Konflikten auf den Stamm zurückzuführen.

Stattdessen könnten Sie und Sally fortfahren, während der Arbeit Änderungen gemeinsam zu verwenden. Es liegt an Ihnen, zu entscheiden, welche Änderungen teilenswert sind; Subversion bietet Ihnen die Fähigkeit, Änderungen selektiv zwischen Zweigen zu kopieren. Und wenn Sie mit Ihrem Zweig vollständig fertig sind, kann die gesamte Menge Ihrer Änderungen vom Zweig auf den Stamm zurück kopiert werden. In der Terminologie von Subversion heißt der allgemeine Vorgang, Änderungen von einem Zweig auf einen anderen zu übertragen Zusammenführen (Merging) und wird durch verschiedene Aufrufe des Befehls svn merge durchgeführt.

In den folgenden Beispielen gehen wir davon aus, dass sowohl auf Ihrem Subversion-Client als auch auf dem Server Subversion 1.5 (oder neuer) läuft. Falls einer von beiden älter als Version 1.5 ist, wird es komplizierter: Das System wird Änderungen nicht automatisch mitverfolgen, so dass Sie schmerzhafte manuelle Methoden anwenden müssen, um ähnliche Resultate zu erzielen. Dass heißt, dass Sie stets die detaillierte Syntax beim Zusammenführen verwenden müssen, um bestimmte Revisionsintervalle zu übertragen (siehe „Merge-Syntax: Die vollständige Enthüllung“ weiter unten in diesem Kapitel), und besonders sorgfältig verfolgen müssen, was bereits zusammengeführt ist und was nicht. Aus diesem Grund empfehlen wir Ihnen dringend, sicherzustellen, dass Ihr Client und Server mindestens die Version 1.5 haben.

Änderungsmengen

Bevor wir weitermachen, sollten wir Sie warnen, dass Sie auf den kommenden Seiten viele Erörterungen zum Thema Änderungen erwarten. Viele mit Versionskontrollsystemen erfahrene Leute benutzen die Begriffe Änderung und Änderungsmenge (Changeset) austauschbar, so dass wir klären sollten, was Subversion unter einer Änderungsmenge versteht.

Jeder scheint eine etwas unterschiedliche Definition für den Begriff Änderungsmenge zu haben oder zumindest eine unterschiedliche Erwartung darüber, was es für ein Versionskontrollsystem bedeutet, so etwas zu besitzen. Für unsere Zwecke reicht es aus, zu sagen, dass eine Änderungsmenge lediglich eine Sammlung von Änderungen mit einem eindeutigen Namen ist. Die Änderungen können aus der Bearbeitung an Textdateien, Modifizierungen an der Baumstruktur oder Justierungen an Metadaten bestehen. In einfachen Worten ist eine Änderungsmenge einfach ein Patch mit einem Namen, auf den Sie sich beziehen können.

In Subversion bezeichnet eine globale Revisionsnummer N einen Baum im Repository: Sie beschreibt das Aussehen des Repositorys nach der N-ten Übergabe. Sie ist auch der Name einer impliziten Änderungsmenge: Wenn Sie den Baum N mit dem Baum N−1 vergleichen, können Sie genau den Patch ableiten, der übergeben wurde. Daher ist es einfach, sich Revision N nicht nur als Baum sondern auch als Änderungsmenge vorzustellen. Falls Sie ein Fehlerverwaltungssystem verwenden, können Sie die Revisionsnummern benutzen, um auf bestimmte Patches zu verweisen, die Fehler beheben – zum Beispiel: Dieser Fehler wurde durch r9238 behoben. Dann kann jemand svn log -r 9238 aufrufen, um den Protokolleintrag zu genau der Änderungsmenge zu lesen, die den Fehler behoben hat, und sich mit svn diff -c 9238 den eigentlichen Patch ansehen. Und auch (wie Sie bald sehen werden) der Subversion Befehl svn merge kann Revisionsnummern verwenden. Sie können bestimmte Änderungsmengen von einem Zweig mit einem anderen zusammenführen, indem sie in den Argumenten zum entsprechenden Kommando benannt werden: Die Übergabe von -c 9238 an svn merge würde das Änderungsmenge r9238 mit Ihrer Arbeitskopie zusammenführen.

Einen Zweig synchron halten

Machen wir mit unserem Beispiel weiter und nehmen an, dass eine Woche vergangen ist seitdem Sie begonnen haben, auf Ihrem privaten Zweig zu arbeiten. Ihre Arbeit ist noch nicht beendet, jedoch wissen Sie, dass gleichzeitig andere Leute in Ihrem Team weiterhin wichtige Änderungen im /trunk des Projektes gemacht haben. Es ist in Ihrem Interesse, diese Änderungen in Ihren Zweig zu übernehmen, um sicherzustellen, dass sie sich gut mit Ihren Änderungen vertragen. Dies ist tatsächlich eine der besten Vorgehensweisen: Ihren Zweig regelmäßig mit der Hauptentwicklungslinie zu synchronisieren hilft, überraschende Konflikte zu vermeiden, wenn es an der Zeit ist, Ihre Änderungen zurück auf den Stamm zu bringen.

Subversion kennt die Geschichte Ihres Zweigs und weiß, wann Sie ihn vom Stamm abgezweigt haben. Um die letzten, aktuellsten Änderungen vom Stamm auf Ihren Zweig zu bringen, sollten Sie zunächst sicherstellen, dass die Arbeitskopie des Zweigs sauber ist – dass sie keine lokalen Änderungen hat, die durch svn status angezeigt werden. Dann rufen Sie einfach die folgenden Befehle auf:

$ pwd
/home/user/my-calc-branch

$ svn merge http://svn.example.com/repos/calc/trunk
--- Zusammenführen von r345 bis r356 in ».«:
U    button.c
U    integer.c

Diese einfache Syntax – svn merge URL – fordert Subversion auf, alle neuen Änderungen von dem URL mit dem aktuellen Arbeitsverzeichnis (welches typischerweise das Wurzelverzeichnis Ihrer Arbeitskopie ist) zusammenzuführen. Nach dem Ausführen des vorangegangenen Beispiels enthält Ihre Arbeitskopie nun neue lokale Änderungen, die Nachbildungen all der Änderungen auf dem Stamm seit der Erstellung Ihres Zweiges sind:

$ svn status
 M     .
M      button.c
M      integer.c

Zu diesem Zeitpunkt ist es weise, sich die Änderungen mithilfe von svn diff sorgfältig anzusehen, und anschließend die Software von Ihrem Zweig zu bauen und zu testen. Beachten Sie, dass auch das aktuelle Arbeitsverzeichnis (.) verändert wurde; svn diff zeigt an, dass seine Eigenschaft svn:mergeinfo entweder angelegt oder modifiziert wurde. Das ist ein wichtiges Metadatum in Zusammenhang mit Zusammenführungen, das Sie nicht anfassen sollten, da es von künftigen svn merge-Befehlen benötigt wird. (Wir werden später in diesem Kapitel mehr über diese Metadaten erfahren.)

Nach der Übernahme kann es möglich sein, dass Sie noch einige Konflikte auflösen müssen (wie bei svn update) oder möglicherweise noch einige kleinere Bearbeitungen durchzuführen haben, damit alles wieder funktioniert. (Denken Sie daran, dass die Abwesenheit syntaktischer Konflikte nicht bedeutet, dass keine semantischen Konflikte vorhanden sind!) Falls ernsthafte Probleme auftauchen, können Sie jederzeit die lokalen Änderungen mit svn revert . -R wieder rückgängig machen und eine lange was geht hier eigentlich vor-Unterredung mit Ihren Mitarbeitern führen. Falls jedoch alles gut aussieht, können Sie die Änderungen an das Repository übergeben:

$ svn commit -m "Die letzten Änderungen von trunk mit my-calc-branch zusammengeführt."
Sende          .
Sende          button.c
Sende          integer.c
Übertrage Daten ..
Revision 357 übertragen.

An dieser Stelle ist Ihr Zweig synchron mit dem Stamm, und Sie können sich ruhig zurücklehnen in der Gewissheit, dass Sie sich nicht zu weit von der Arbeit aller anderen entfernen, während Sie isoliert weiterarbeiten.

Nehmen wir an, noch eine Woche sei ins Land gegangen. Sie haben weitere Änderungen an Ihren Zweig übergeben, und Ihre Kollegen haben damit weitergemacht, den Stamm zu verbessern. Nun möchten Sie mal wieder die letzten Änderungen vom Stamm mit Ihrem Zweig abgleichen, damit Sie wieder synchron sind. Starten Sie einfach noch einmal den svn merge-Befehl!

$ svn merge http://svn.example.com/repos/calc/trunk
--- Zusammenführen von r357 bis r380 in ».«:
U    integer.c
U    Makefile
A    README

Subversion weiß, welche Änderungen Sie bereits mit Ihrem Zweig abgeglichen haben, so dass es sorgfältig nur die Änderungen berücksichtigt, die Sie noch nicht haben. Einmal mehr müssen Sie bauen, testen und die lokalen Änderungen an Ihren Zweig mit svn commit