Diese Dokumentation wurde zur Beschreibung der Serie 1.6.x von Subversion erstellt. Falls Sie eine unterschiedliche Version von Subversion einsetzen, sei Ihnen dringend angeraten, bei http://www.svnbook.com/ vorbeizuschauen und stattdessen die zu Ihrer Version von Subversion passende Version dieser Dokumentation heranzzuiehen.

Externals-Definitionen

Manchmal kann es nützlich sein, eine Arbeitskopie anzulegen, die aus einer Anzahl verschiedener Checkouts besteht. Es könnte beispielsweise sein, dass Sie verschiedene Unterverzeichnisse aus verschiedenen Bereichen des Projektarchivs haben möchten oder vielleicht sogar aus völlig verschiedenen Projektarchiven. Natürlich könnten Sie ein solches Szenario manuell erstellen – indem Sie svn checkout verwenden, um die verschachtelte Verzeichnisstruktur Ihrer Wahl anzulegen. Wenn diese Struktur jedoch für jeden Benutzer Ihres Projektarchivs wichtig ist, müsste jeder andere Benutzer dieselben Checkouts ausführen wie Sie.

Glücklicherweise unterstützt Subversion Externals-Definitionen. Eine Externals-Definition ist eine Abbildung eines lokalen Verzeichnisses auf den URL – und idealerweise eine bestimmte Revision – eines versionierten Verzeichnisses. In Subversion deklarieren Sie Externals-Definitionen in Gruppen unter Verwendung der Eigenschaft svn:externals. Sie können diese Eigenschaft mit svn propset oder svn propedit erstellen oder ändern (siehe „Ändern von Eigenschaften“). Sie kann jedem versionierten Verzeichnis zugeordnet werden, und ihr Wert beschreibt sowohl die Adresse des externen Projektarchivs als auch das Verzeichnis auf dem Client, in dem diese Adresse ausgecheckt werden soll.

Sobald sie mit einem versionierten Verzeichnis verknüpft ist, bietet die Eigenschaft svn:externals den Komfort, dass jeder, der eine Arbeitskopie mit diesem Verzeichnis auscheckt, die Vorteile der Externals-Definition mitbekommt. Mit anderen Worten: Sobald sich jemand die Mühe gemacht hat, die verschachtelte Struktur der Arbeitskopie zu definieren, braucht sich niemand mehr darum zu kümmern – Subversion checkt nach der ursprünglichen Arbeitskopie automatisch die externen Arbeitskopien aus.

[Warnung] Warnung

Die relativen Zielverzeichnisse von Externals-Definitionen dürfen nicht bereits auf Ihrem oder dem Systemen anderer Benutzer vorhanden sein – Subversion erzeugt sie beim Auschecken der externen Arbeitskopie.

Mit dem Design der Externals-Definition bekommen Sie auch alle normalen Vorteile der Subversion-Eigenschaften. Die Definitionen sind versioniert. Falls Sie eine Externals-Definition ändern müssen, können Sie das mit den üblichen Unterbefehlen zum Ändern von Eigenschaften bewerkstelligen. Wenn Sie eine Änderung an der Eigenschaft svn:externals übergeben, wird Subversion beim nächsten svn update die ausgecheckten Elemente mit der geänderten Externals-Definition synchronisieren. Dasselbe passiert, wenn andere ihre Arbeitskopie aktualisieren und Ihre Änderungen an der Externals-Definition erhalten.

[Tipp] Tipp

Da die Eigenschaft svn:externals einen mehrzeiligen Wert besitzt, empfehlen wir dringend, dass Sie svn propedit statt svn propset verwenden.

Subversion-Versionen vor 1.5 akzeptieren ein Format für Externals-Definitionen, welches eine mehrzeilige Tabelle ist, die aus Unterverzeichnissen (relativ zum versionierten Verzeichnis, mit dem die Eigenschaft verknüpft ist), optionalen Revisions-Flags und vollqualifizierten, absoluten Subversion-Projektarchiv-URLs besteht. Ein Beispiel könnte so aussehen:

$ 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

Wenn jemand eine Arbeitskopie des Verzeichnisses calc aus dem obigen Beispiel auscheckt, fährt Subversion damit fort, die Objekte in der Externals-Definition auszuchecken.

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

Hole externen Verweis nach 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
Ausgecheckt. Revision 14.

Hole externen Verweis nach calc/third-party/skins
…

Seit Subversion 1.5 wird jedoch ein neues Format der Eigenschaft svn:externals unterstützt. Die Externals-Definitionen sind immer noch mehrzeilig, jedoch hat sich die Reihenfolge und das Format der verschiedenen Informationen geändert. Die neue Syntax lehnt sich nun mehr an die Reihenfolge der Argumente an, die Sie svn checkout übergeben: Zunächst kommen die Revisions-Flags, dann der URL des externen Subversion-Projektarchivs und schließlich das relative lokale Unterverzeichnis. Beachten Sie jedoch, dass wir diesmal nicht von vollqualifizierten, absoluten Subversion-Projektarchiv-URLs gesprochen haben. Das liegt daran, dass das neue Format relative URLs und URLs mit Peg-Revisionen unterstützt. Das vorausgegangene Beispiel einer Externals-Definition könnte in Subversion 1.5 so aussehen:

$ 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

Bei Verwendung der Syntax für Peg-Revisionen (die wir detailliert in „Peg- und operative Revisionen“ behandeln), könnte es so aussehen:

$ 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

Sie sollten ernsthaft erwägen, explizite Revisionsnummern in all Ihren Externals-Definitionen zu verwenden. Wenn Sie das tun, bedeutet dies, dass Sie entscheiden, wann ein anderer Schnappschuss mit externen Informationen herangezogen werden soll und welcher Schnappschuss genau. Außer der Vermeidung überraschender Änderungen an Projektarchiven Dritter, auf die Sie keinen Einfluss haben, bedeuten explizite Revisionsnummern, dass beim Zurücksetzen Ihrer Arbeitskopie auf eine frühere Revision auch die Externals-Definitionen auf den entsprechenden früheren Stand zurückgesetzt werden, was wiederum bedeutet, dass die externen Arbeitskopien derart aktualisiert werden, dass sie so aussehen wie zum Zeitpunkt Ihres Projektarchivs der früheren Revision. Für Software-Projekte kann das den Unterschied zwischen einem erfolgreichen und einem gescheiterten Build eines älteren Schnappschusses Ihrer komplexen Codebasis ausmachen.

Bei den meisten Projektarchiven bewirken die drei Formate der Externals-Definition letztendlich dasselbe. Alle bringen die gleichen Vorteile. Leider bringen alle aber auch die gleichen Ärgernisse. Da die Definitionen absolute URLs verwenden, hat das Kopieren oder Verschieben eines damit verknüpften Verzeichnisses keine Auswirkungen auf das, was als extern ausgescheckt wird (obwohl natürlich das relative lokale Zielverzeichnis mit dem umbenannten Verzeichnis mitwandert). Das kann in bestimmten Situationen verwirrend – sogar frustrierend – sein. Nehmen wir beispielsweise an, dass Sie ganz oben ein Verzeichnis namens my-project haben und eine Externals-Definition auf eins seiner Unterverzeichnisse erstellt haben (my-project/some-dir), welches wiederum die letzte Revision eines anderen Unterverzeichnisses verfolgt (my-project/external-dir).

$ svn checkout http://svn.example.com/projects .
A    my-project
A    my-project/some-dir
A    my-project/external-dir
…
Hole externen Verweis nach »my-project/some-dir/subdir«
Externer Verweis ausgecheckt, Revision 11.

Ausgecheckt, Revision 11.
$ svn propget svn:externals my-project/some-dir
subdir http://svn.example.com/projects/my-project/external-dir

$

Nun benennen Sie mit svn move das Verzeichnis my-project um. Zu diesem Zeitpunkt verweist Ihre Externals-Definition noch immer auf einen Pfad unterhalb des Verzeichnisses my-project, obwohl das Verzeichnis nicht mehr existiert.

$ svn move -q my-project renamed-project
$ svn commit -m "Rename my-project to renamed-project."
Lösche         my-project
Hinzufügen     renamed-project

Revision 12 übertragen.
$ svn update

Hole externen Verweis nach »renamed-project/some-dir/subdir«
svn: Zielpfad existiert nicht
$

Absolute URLs können außerdem Probleme bei Projektarchiven hervorrufen, die über verschiedene URL-Schemata verfügbar sind. Falls Ihr Subversion-Server so konfiguriert sein sollte, dass jeder das Projektarchiv über http:// oder https:// auschecken darf, Übertragungen jedoch nur über https:// erlaubt sind, haben Sie ein interessantes Problem. Wenn Ihre Externals-Definitionen die http://-Form der Projektarchiv-URLs verwenden, werden Sie nicht im Stande sein, irgend etwas aus den mit diesen Externals erzeugten Arbeitskopien zu übertragen. Wenn Sie andererseits die https://-Form der URLs verwenden, kann jemand, der mit http:// auscheckt, da sein Client https:// nicht unterstützt, die externen Verweise nicht heranziehen. Beachten Sie ferner, dass beim Umhängen Ihrer Arbeitskopie (mit svn switch und der Option --relocate) die Externals-Definitionen nicht automatisch umgehängt werden.

Subversion 1.5 unternimmt einen riesigen Schritt, um diese Frustrationen zu lindern. Wie bereits früher erwähnt wurde, können die URLs im neuen Externals-Format relativ sein, und Subversion stellt eine besondere Syntax zur Verfügung, um verschiedene Arten relativer URLs darzustellen.

../

Relativ zum URL des Verzeichnisses, an dem die Eigenschaft svn:externals gesetzt ist

^/

Relativ zur Wurzel des Projektarchivs, in dem die Eigenschaft svn:externals versioniert ist

//

Relativ zum Schema des URL des Verzeichnisses, an dem die Eigenschaft svn:externals gesetzt ist

/

Relativ zum Wurzel-URL des Servers, auf dem die Eigenschaft svn:externals versioniert ist

Wenn wir uns nun ein viertes Mal das vorangegangene Beispiel mit der Externals-Definition ansehen und von der neuen absoluten URL-Syntax auf verschiedene Weise Gebrauch machen, könnten wir nun das sehen:

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

Subversion 1.6 bringt zwei weitere Verbesserungen für Externals-Definitionen. Zunächst erweitert es die Syntax um einen Zitier- und Maskierungsmechanismus, so dass der Pfad der externen Arbeitskopie Leerzeichen enthalten darf. Das war vorher natürlich problematisch, da Leerzeichen zum Begrenzen von Feldern einer externals Definition verwendet wurden. Nun müssen Sie eine solche Pfad-Spezifizierung lediglich in doppelte Anführungszeichen (") einpacken oder die problematischen Zeichen im Pfad mit einem rückwärtigen Schrägstrich (\) maskieren. Wenn Sie Leerzeichen im URL-Teil der Externals-Definition haben, sollten Sie dafür natürlich den Standard-URI-Encoding-Mechanismus verwenden.

$ svn propget svn:externals paint
http://svn.thirdparty.com/repos/My%20Project "My Project"
http://svn.thirdparty.com/repos/%22Quotes%20Too%22 \"Quotes\ Too\"
$

Subversion 1.6 führt ebenfalls die Unterstützung von Externals-Definitionen für Dateien ein. File Externals werden wie Externals für Verzeichnisse konfiguriert und erscheinen in der Arbeitskopie als versionierte Datei.

Nehmen wir beispielsweise an, die Datei /trunk/bikeshed/blue.html sei in Ihrem Projektarchiv vorhanden, und Sie möchten diese Datei gerne wie in Revision 40 in Ihrer Arbeitskopie von /trunk/www/ unter dem Namen green.html haben.

Die hierfür benötigte Externals-Definition sollte nun vertraut aussehen:

$ svn propget svn:externals www/
^/trunk/bikeshed/blue.html@40 green.html
$ svn update
Hole externen Verweis nach »www«
E    www/green.html
Externer Verweis aktualisiert zu Revision 40.

Aktualisiert zu Revision 103.
$ svn status
    X   www/green.html
$

Wie Sie in der vorangegangenen Ausgabe sehen können, markiert Subversion Datei-Externals mit dem Buchstaben E wenn sie in die Arbeitskopie geholt werden und mit dem Buchstaben X wenn der Zustand der Arbeitskopie angezeigt wird.

[Warnung] Warnung

Während Verzeichnis-Externals das externe Verzeichnis in eine beliebige Tiefe setzen können und sämtliche fehlende Zwischenverzeichnisse erstellt werden, müssen Datei-Externals in die bereits ausgecheckte Arbeitskopie gesetzt werden.

Wenn Sie das Datei-External mit svn info untersuchen, können Sie den URL und die Revision der Herkunft des Externals sehen.

$ svn info www/green.html 
Path: www/green.html
Name: green.html
URL: http://svn.example.com/projects/my-project/trunk/bikeshed/blue.html
Repository Root: http://svn.example.com/projects/my-project
Repository UUID: b2a368dc-7564-11de-bb2b-113435390e17
Revision: 40
Node kind: file
Schedule: normal
Last Changed Author: harry
Last Changed Rev: 40
Last Changed Date: 2009-07-20 20:38:20 +0100 (Mon, 20 Jul 2009)
Text Last Updated: 2009-07-20 23:22:36 +0100 (Mon, 20 Jul 2009)
Checksum: 01a58b04617b92492d99662c3837b33b
$

Da Datei-Externals in der Arbeitskopie als versionierte Dateien erscheinen, können sie bearbeitet und sogar übergeben werden, falls sie auf eine Datei in der HEAD-Revision verweisen. Die übergebenen Änderungen erscheinen dann sowohl im External als auch in der Datei, auf die das External verweist. In unserem Beispiel allerdings verwies das External auf eine ältere Revision, so dass der Versuch scheitert, das External zu übergeben:

$ svn status
M   X   www/green.html
$ svn commit -m "change the color" www/green.html
Sende          www/green.html
svn: Übertragen schlug fehl (Details folgen)::
svn: Datei »/trunk/bikeshed/blue.html« ist veraltet
$

Denken Sie daran, wenn Sie Datei-Externals definieren. Falls Sie wünschen, dass das External auf eine bestimmte Revision einer Datei verweist, werden Sie das External nicht modifizieren können. Wenn Sie in der Lage sein wollen, das External zu bearbeiten, können Sie keine andere Revision außer HEAD angeben, die auch implizit gesetzt wird, wenn Sie keine Revision angeben.

Leider bleibt die Unterstützung für Externals-Definitionen in Subversions alles andere als ideal. Sowohl Datei- als auch Verzeichnis-Externals haben Schwächen. Für beide Arten von Externals darf der lokale Unterverzeichnis-Teil keine ..-Verweise auf Elternverzeichnisse enthalten (etwa ../../skins/myskin). Datei-Externals können nicht auf Dateien aus anderen Projektarchiven verweisen. Der URL eines Datei-Externals muss stets im selben Projektarchiv liegen, wie der URL, in den das Datei-External eingefügt wird. Außerdem können Datei-Externals weder verschoben noch gelöscht werden. Stattdessen muss die Eigenschaft svn:externals geändert werden. Allerdings können Datei-Externals kopiert werden.

Am enttäuschendsten ist vielleicht, dass die Arbeitskopieen, die über die Unterstützung von Externals-Definitionen angelegt wurden, immer noch nicht mit der primäten Arbeitskopie verbunden sind (an deren versionierten Verzeichnissen die Eigenschaft svn:externals tatsächlich gesetzt wurde). Und Subversion arbeitet immer noch wirklich nur auf disjunkten Arbeitskopien. Wenn Sie also beispielsweise Änderungen übergeben möchten, die Sie in einer oder mehreren dieser externen Arbeitskopien vorgenommen haben, müssen Sie explizit svn commit auf diesen Arbeitskopien aufrufen – die Übergabe in der primären Arbeitskopie wird sich nicht rekursiv in externe fortpflanzen.

Wir haben bereits einige der Mängel des alten Formats von svn:externals und die Verbesserungen durch das neue Format von Subversion 1.5 erwähnt. Seien Sie jedoch vorsichtig, dass Sie bei Verwendung des neuen Formats nicht versehentlich neue Probleme verursachen. Während beispielsweise die neuesten Clients weiterhin das ursprüngliche Format der Externals-Definitionen verstehen und unterstützen, sind vor-1.5 Clients nicht in der Lage, das neue Format korrekt zu verarbeiten. Falls Sie alle Ihre Externals-Definitionen in das neue Format ändern, zwingen Sie effektiv jeden, der diese Externals verwendet, Ihre Subversion-Clients auf eine Version zu bringen, die dieses Format versteht. Vermeiden Sie auch, den -rNNN-Teil der Definition naiverweise umzuschreiben – das ältere Format verwendet diese Revision als eine Peg-Revision, wohingegen das neuere Format sie als eine operativer Revision verwendet (mit einer Peg-Revision von HEAD, wenn nicht anders angegeben; siehe „Peg- und operative Revisionen“ für eine vollständige Erklärung der hiesigen Unterscheidung).

[Warnung] Warnung

Externe Arbeitskopien sind immer noch vollständig unabhängige Arbeitskopien. Sie können direkt auf ihnen arbeiten wie in jeder anderen Arbeitskopie. Das kann sehr praktisch sein, da es Ihnen ermöglicht, eine externe Arbeitskopie zu untersuchen, unabhängig von irgendeiner primären Arbeitskopie, deren svn:externals-Eigenschaft ihre Instantiierung veranlasste. Seien Sie trotzdem vorsichtig, damit Sie nicht versehentlich Ihre externe Arbeitskopie auf raffinierte Art modifizieren, so dass Probleme entstehen. Wenn beispielsweise eine Externals-Definition spezifiziert, dass eine externe Arbeitskopie in einer bestimmtern Revision vorgehalten werden soll, und Sie svn update direkt auf der externen Arbeitskopie aufrufen, wird Subversion Ihnen gehorchen und Ihre externe Arbeitskopie ist nicht mehr synchron mit ihrer Deklaration in der primären Arbeitskopie. Die Verwendung von svn switch, um direkt die externe Arbeitskopie (oder Teile davon) auf einen anderen URL zu wechseln, kann ähnliche Probleme verursachen, falls die Inhalte der primären Arbeitskopie bestimmte externe Inhalte voraussetzen.

Neben den Befehlen svn checkout, svn update, svn switch und svn export, welche die disjunkten (oder unzusammenhängenden) Unterverzeichnisse mit den ausgecheckten Externals eigentlich verwalten, berücksichtigt auch der Befehl svn status Externals-Definitionen. Er zeigt für die disjunkten externen Unterverzeichnisse einen Zustandscode X an und durchläuft dann diese Verzeichnisse, um den Zustand der eigentlichen externen Objekte anzuzeigen. Sie können jedem dieser Unterbefehle die Option --ignore-externals mitgeben, um die Bearbeitung der Externals-Definitionen zu unterbinden.