Dieser Text befindet sich gegenwärtig in Bearbeitung, unterliegt ständigen Änderungen und kann dadurch nicht stets akkurat irgendeine freigegebene Version der Software Apache™ Subversion® beschreiben. Das Speichern dieser Seite als Lesezeichen oder andere auf diese Seite zu verweisen, ist keine so gute Idee. Besuchen Sie http://www.svnbook.com/, um stabile Versionen dieses Buchs zu erhalten.
Bis hierhin haben wir nur über Konflikte auf der Ebene von Dateiinhalten gesprochen. Wenn Sie und Ihre Mitarbeiter überlappende Änderungen innerhalb derselben Datei vornehmen, zwingt Sie Subversion dazu, diese Änderungen zusammenzuführen, bevor Sie sie übertragen können.[9]
Was passiert aber, wenn Ihre Mitarbeiter eine Datei verschieben oder löschen, an der Sie noch arbeiten? Vielleicht gab es ein Verständnisproblem oder die eine Person glaubt, die Datei soll gelöscht werden, während die andere Person noch Änderungen an der Datei übertragen will. Vielleicht haben Ihre Mitarbeiter ja auch etwas Refactoring betrieben und dabei Dateien umbenannt und Verzeichnisse verschoben. Falls Sie noch an diesen Dateien gearbeitet haben, müssten diese Änderungen auf die Dateien am der neuen Stelle angewendet werden. Derartige Konflikte äußern sich auf der Ebene der Verzeichnisstruktur statt des Dateiinhaltes und sind bekannt als Baumkonflikte.
Wie bei textuellen Konflikten verhindern Baumkonflikte eine Übergabe aus dem Konfliktzustand und geben dem Anwender die Gelegenheit, den Zustand der Arbeitskopie auf potenzielle Probleme, die aus dem Baumkonflikt entstehen könnten, zu überprüfen und vor der Übergabe aufzulösen.
Gegeben sei folgendes Softwareprojekt, an dem Sie gerade arbeiten:
$ svn list -Rv svn://svn.example.com/trunk/ 13 harry Sep 06 10:34 ./ 13 harry 27 Sep 06 10:34 COPYING 13 harry 41 Sep 06 10:32 Makefile 13 harry 53 Sep 06 10:34 README 13 harry Sep 06 10:32 code/ 13 harry 54 Sep 06 10:32 code/bar.c 13 harry 130 Sep 06 10:32 code/foo.c $
Später, in Revision 14, benennt Ihr Kollege Harry die
Datei bar.c
in baz.c
um. Sie merken das noch nicht. Wie sich herausstellt, sind Sie
in Ihrer Arbeitskopie damit beschäftigt, eine Menge
unterschiedlicher Änderungen vorzunehmen, von denen einige
auch bar.c
berühren:
$ svn diff Index: code/foo.c =================================================================== --- code/foo.c (revision 13) +++ code/foo.c (working copy) @@ -3,5 +3,5 @@ int main(int argc, char *argv[]) { printf("I don't like being moved around!\n%s", bar()); - return 0; + return 1; } Index: code/bar.c =================================================================== --- code/bar.c (revision 13) +++ code/bar.c (working copy) @@ -1,4 +1,4 @@ const char *bar(void) { - return "Me neither!\n"; + return "Well, I do like being moved around!\n"; } $
Sie bemerken erst, dass jemand anderes
bar.c
geändert hat, als Ihr eigener
Übertragungsversuch scheitert:
$ svn commit -m "Small fixes" Sende code/bar.c Übertrage Daten . svn: E155011: Übertragen schlug fehl (Details folgen): svn: E155011: Datei »/home/svn/project/code/bar.c« ist veraltet svn: E160013: Datei nicht gefunden: Transaktion »14-e«, Pfad »/code/bar.c« $
An dieser Stelle müssen Sie svn update aufrufen. Außer Ihre Arbeitskopie zu aktualisieren, so dass Sie Harrys Änderungen sehen können, markiert es auch einen Baumkonflikt, so dass Sie die Gelegenheit bekommen, die Situation abzuschätzen und entsprechend aufzulösen.
$ svn update Updating '.': C code/bar.c A code/baz.c U Makefile Aktualisiert zu Revision 5. Konfliktübersicht: Baumkonflikte: 1
In seiner Ausgabe zeigt svn update Baumkonflikte mit einem großen C in der vierten Spalte an. svn status enthüllt weitere Details zum Konflikt:
$ svn status M code/foo.c A + C code/bar.c > local edit, incoming delete upon update Konfliktübersicht: Baumkonflikte: 1 $
Beachten Sie, wie bar.c
automatisch
in Ihrer Arbeitskopie zum erneuten Hinzufügen vorgemerkt wird,
was die Sache vereinfacht, sollten sie sich entscheiden, die
Datei zu behalten.
Da eine Verschiebung in Subversion als eine Kopie mit anschließender Löschung implementiert ist, und diese beiden Operationen sich bei einer Aktualisierung sich nicht einfach in Beziehung setzen lassen, kann Sie Subversion lediglich über eine hereinkommende Löschung einer lokal modifizierten Datei warnen. Diese Löschung kann Teil einer Verschiebung sein oder eine tatsächliche Löschung. Es ist wichtig, herauszufinden, welche semantische Änderung genau am Projektarchiv vorgenommen wurde – Sie sollten wissen, wie sich Ihre Änderungen in das Gesamtbild des Projektes einpassen lassen. Lesen Sie also die Protokokllnachrichten, halten Sie mit Ihren Kollegen Rücksprache, begutachten Sie die zeilenbasierten Änderungen – machen Sie, was auch immer zu tun ist – um Ihre nächsten Schritte zu bestimmen.
In diesem Fall verrät Ihnen die Protokollnachricht der Übertragung von Harry alles, was Sie wissen müssen.
$ svn log -r14 ^/trunk ------------------------------------------------------------------------ r14 | harry | 2011-09-06 10:38:17 -0400 (Di, 06. Sep 2011) | 1 Zeile Geänderte Pfade: M /Makefile D /code/bar.c A /code/baz.c (from /code/bar.c:13) Rename bar.c to baz.c, and adjust Makefile accordingly. ------------------------------------------------------------------------ $
svn info zeigt die URLs der am Konflikt beteiligten Objekte. Der linke URL zeigt die Quelle der lokalen Seite des Konfliktes, während die rechte URL die Quelle der hereinkommenden Seite des Konfliktes anzeigt. Diese URLs weisen darauf hin, wo Sie mit der Suche nach der mit Ihrer lokalen Änderung in Konflikt stehenden Änderung in der Vorgeschichte des Projektarchivs beginnen sollten.
$ svn info code/bar.c Pfad: code/bar.c Name: bar.c URL: http://svn.example.com/svn/repo/trunk/code/bar.c … Baumkonflikt: lokal editiert, eingehend gelöscht bei Aktualisierung Quelle links: (Datei) ^/trunk/code/bar.c@4 Quelle rechts: (nichts) ^/trunk/code/bar.c@5 $
bar.c
heißt nun Opfer eines
Baumkonfliktes. Sie kann nicht übertragen werden, bevor der
Konflikt aufgelöst wird:
$ svn commit -m "Small fixes" svn: E155015: Übertragen schlug fehl (Details folgen): svn: E155015: Übertragung abgebrochen: »/home/svn/project/code/bar.c« bleibt im Konflikt $
Um diesen Konflikt aufzulösen, müssen Sie entweder mit Harrys Vorgehen einverstanden sein oder nicht.
Falls Sie mit dem Vorgehen einverstanden sind, ist Ihr
bar.c
überflüssig. Sie können es löschen
und den Baumkonflikt als aufgelöst markieren. Aber halt: Sie
haben Änderungen an der Datei vorgenommen! Bevor Sie
bar.c
löschen, müssen Sie entscheiden, ob
die von Ihnen gemachten Änderungen an einer anderen Stelle
vorgenommen werden müssen, zum Beispiel an der neuen Datei
baz.c
, in der sich nun der Code aus
bar.c
befindet. Wir nehmen einmal an,
dass Ihre Änderungen tatsächlich müssen „der
Verschiebung folgen“ müssen. Subversion ist nicht
schlau genug, um diese Arbeit für Sie zu
übernehmen[10], so dass Sie
Ihre Änderungen manuell übertragen müssen.
In unserem Beispiel könnten Sie einfach Ihre Änderungen an
bar.c
noch einmal vornehmen – es
war schließlich nur eine Änderung in einer Zeile. Das ist
allerdings nicht immer der Fall, weshalb wir einen
skalierbareren Ansatz zeigen. Zunächst erzeugen wir mit
svn diff eine Patch-Datei. Dann bearbeiten
wir die Kopfzeilen dieser Patch-Datei, so dass sie auf den
neuen Namen der umbenannten Datei zeigen. Schließlich wenden
wir den modifizierten Patch erneut auf unsere Arbeitskopie
an.
$ svn diff code/bar.c > PATCHFILE $ cat PATCHFILE Index: code/bar.c =================================================================== --- code/bar.c (revision 14) +++ code/bar.c (working copy) @@ -1,4 +1,4 @@ const char *bar(void) { - return "Me neither!\n"; + return "Well, I do like being moved around!\n"; } $ ### PATCHFILE bearbeiten, so dass es sich auf code/baz.c statt auf code/bar.c bezieht $ cat PATCHFILE Index: code/baz.c =================================================================== --- code/baz.c (revision 14) +++ code/baz.c (working copy) @@ -1,4 +1,4 @@ const char *bar(void) { - return "Me neither!\n"; + return "Well, I do like being moved around!\n"; } $ svn patch PATCHFILE U code/baz.c $
Da nun die ursprünglich an to bar.c
vorgenommenen Änderungen erfolgreich in
baz.c
reproduziert wurden, können Sie
bar.c
löschen und den Konflikt auflösen,
indem Sie die Auflösungslogik anweisen, den aktuellen Inhalt
der Arbeitskopie als das gewünschte Ergebnis zu
akzeptieren.
$ svn delete --force code/bar.c D code/bar.c $ svn resolve --accept=working code/bar.c Konflikt von »code/bar.c« aufgelöst $ svn status M code/foo.c M code/baz.c $ svn diff Index: code/foo.c =================================================================== --- code/foo.c (revision 14) +++ code/foo.c (working copy) @@ -3,5 +3,5 @@ int main(int argc, char *argv[]) { printf("I don't like being moved around!\n%s", bar()); - return 0; + return 1; } Index: code/baz.c =================================================================== --- code/baz.c (revision 14) +++ code/baz.c (working copy) @@ -1,4 +1,4 @@ const char *bar(void) { - return "Me neither!\n"; + return "Well, I do like being moved around!\n"; } $
Falls Sie mit dem Vorgehen nicht einverstanden sind,
können Sie stattdessen baz.c
löschen,
nachdem Sie sichergestellt haben, das alle nach der
Umbenennung vorgenommenen Änderungen entweder bewahrt worden
sind, oder verworfen werden können. Vergessen Sie nicht, die
Änderungen zurückzunehmen, die Harry an
Makefile
gemacht hat. Da
bar.c
bereits zum neu Hinzufügen
vorgemerkt ist, bleibt nichts mehr zu tun, und der Konflikt
kann als aufgelöst markiert werden:
$ svn delete --force code/baz.c D code/baz.c $ svn resolve --accept=working code/bar.c Konflikt von »code/bar.c« aufgelöst $ svn status M code/foo.c A + code/bar.c D code/baz.c M Makefile $ svn diff Index: code/foo.c =================================================================== --- code/foo.c (revision 14) +++ code/foo.c (working copy) @@ -3,5 +3,5 @@ int main(int argc, char *argv[]) { printf("I don't like being moved around!\n%s", bar()); - return 0; + return 1; } Index: code/bar.c =================================================================== --- code/bar.c (revision 14) +++ code/bar.c (working copy) @@ -1,4 +1,4 @@ const char *bar(void) { - return "Me neither!\n"; + return "Well, I do like being moved around!\n"; } Index: code/baz.c =================================================================== --- code/baz.c (revision 14) +++ code/baz.c (working copy) @@ -1,4 +0,0 @@ -const char *bar(void) -{ - return "Me neither!\n"; -} Index: Makefile =================================================================== --- Makefile (revision 14) +++ Makefile (working copy) @@ -1,2 +1,2 @@ foo: - $(CC) -o $@ code/foo.c code/baz.c + $(CC) -o $@ code/foo.c code/bar.c
Sie haben nun Ihren ersten Baumkonflikt aufgelöst! Sie können Ihre Änderungen übertragen und Harry in der Kaffeepause erzählen, welche Mehrarbeit er Ihnen bereitet hat.
[9] Natürlich könnten Sie Dateien, die Konfliktmarkierungen enthalten, als konfliktfrei erklären und übertragen, wenn Sie es wirklich wollten, doch das wird in der Praxis kaum gemacht.
[10] In manchen Fällen hätten Subversion 1.5 und 1.6 das für Sie gemacht, doch ist diese Aufs-Geratewohl-Funktionalität in Subversion 1.7 entfernt worden.