Eine vernünftige Möglichkeit, ein Verzeichnis in einer Subversion-Arbeitskopie umzubenennen

68

Obwohl ich mich irgendwie mit VCS auskenne (regulärer svn-, git- und git-svn-Benutzer), kann ich mich nicht um dieses eigentümliche SVN-Verhalten kümmern.

Wann immer ich ein Verzeichnis in meiner SVN-Arbeitskopie aus einem ansonsten 'sauberen' Zustand umbenennen muss - dh svn statusnichts zurückgeben und alle anderen Änderungen festgeschrieben wurden - wie dies (was das SVN-Dokument vorschlägt):

svn mv foo bar
svn commit

SVN beschwert sich laut:

Adding         bar
Adding         bar/toto
Deleting       foo
svn: Commit failed (details follow):
svn: Item '/test/foo' is out of date

Wie du möchtest:

svn update

Welches gibt:

   C foo
At revision 46.
Summary of conflicts:
  Tree conflicts: 1

Es gibt einen Baumkonflikt, während keine Änderung durch Dritte stattgefunden hat . Offensichtlich ist der einzige Weg, um aus diesem Baumkonflikt-Chaos herauszukommen, generisch (aus dem roten Buch von svn):

svn resolve --accept working -R .
svn commit

Das Umbenennen im Repo per Fernzugriff und das Aktualisieren meiner Arbeitskopie scheint ziemlich umständlich:

url=$(svn info | grep -e '^URL:' | sed 's/^URL: //') svn mv $url/foo $url/bar
svn update

Gibt es eine sanktionierte, optimierte Möglichkeit, einen fehlenden Ordner umzubenennen? Was ist die Hauptursache für diesen besonders überraschenden Baumkonfliktzustand?

Lloeki
quelle
Können Sie die genaue Baumkonfliktnachricht veröffentlichen?
Albin Sunnanbo
Ich habe dieses Verhalten auch schon einmal gesehen, bin mir aber nicht sicher, was es verursacht. Ist es, wenn Sie ein Verzeichnis hinzufügen und es umbenennen, bevor Sie es festschreiben?
Edd Barrett
Ich habe dieses Verhalten auch erlebt und konnte keinen Grund herausfinden. Ich habe es immer auf "die Art und Weise, wie SVN funktioniert" gebracht. Es macht mich verrückt.
Alex J
Albin, die Nachricht geht außerhalb des GNU-Bildschirmpufferbereichs verloren: /
Lloeki
vext01, dir add wurde schon lange zuvor an svn übergeben svn mv. Dateien im Inneren erhielten Arbeit und wurden vor festgeschrieben svn mv.
Lloeki

Antworten:

70

svn mv funktioniert bei mir:

C:\svn\co>svn mv my_dir new_dir
A         new_dir
D         my_dir\New Text Document.txt
D         my_dir


C:\svn\co>svn commit -m foo
Raderar             my_dir
Lägger till         new_dir

Arkiverade revision 2.

C:\svn\co>

Entschuldigung für die schwedische Ausgabe von svn.

Es muss noch etwas anderes in Ihrem Fall falsch sein.

Bearbeiten:
Wie in den Kommentaren von Lloeki ausgeführt

Um das Verhalten zu reproduzieren, müssen Sie auch eine im Ordner enthaltene Datei aktualisieren und festschreiben, jedoch nicht den Ordner selbst aktualisieren.

Durch das Festschreiben der Datei wird eine neue Version des Repos erstellt, aber die lokalen Metadaten werden nicht aktualisiert (wie immer, siehe SVN-Protokoll nach jedem Festschreiben). Daher befinden sich die Dir-Metadaten bei Version 1. Daraus folgt, dass svn aufgrund des Metadatendifferenz nicht festgeschrieben wird und nicht aktualisiert wird, da tatsächlich ein Konflikt im Verzeichnis vorliegt: Aktualisieren von Metadaten vs. Löschen.

Das Verhalten ist "erwartet" und die "Lösung" besteht darin, die Arbeitskopie vor der Ausgabe des svn renameBefehls zu aktualisieren .

Albin Sunnanbo
quelle
2
Das Finden von 'etwas anderem' ist tatsächlich Teil der Frage :) Ändern Sie nun New Text Document.txt, schreiben Sie es fest, mv das Verzeichnis und schreiben Sie es erneut fest.
Lloeki
1
@Lloeki, ja, durch Ändern der Textdatei wird der Baumkonflikt reproduziert. Für mich sieht es wirklich nach einem Fehler aus. Haben Sie den Issue-Tracker unter subversion.apache.org durchsucht und / oder dort einen Fehlerbericht eingereicht?
Albin Sunnanbo
2
Ich habe schließlich den Grund gefunden, der auf unterwanderte Weise sinnvoll ist: Datei-Commit erstellt eine neue Rev n im Repo, aber lokale Metadaten werden nicht aktualisiert (wie immer, siehe svn lognach jedem Commit), daher befinden sich Dir-Metadaten bei Rev n-1 . Daraus folgt, dass svn aufgrund des Metadatenunterschieds keine Festschreibung vornimmt und nicht aktualisiert wird, da tatsächlich ein Konflikt im Verzeichnis vorliegt: Metadaten aktualisieren vs. löschen.
Lloeki
1
Da Sie mich auf die Strecke gebracht haben, aktualisieren Sie Ihre Antwort und ich werde sie validieren.
Lloeki
Das obige "svn mv my_dir new_dir" hat bei mir funktioniert. Danach konnte ich normales SVN-Commit von Windows
GUI verwenden
8

OK, ich bin darauf gestoßen - und kann das Problem schließlich mit einer einfachen Terminalsitzung rekonstruieren: Das Problem tritt auf, wenn Sie svn mveine Datei (verschieben / umbenennen); dann begehen Sie diese Änderung; dann ( ohne einen tun svn updatezuerst), svn mvdas übergeordnete Verzeichnis der Datei , deren Verschieben / Umbenennen wurde zuvor begangen - und schließlich ein tun svn commitauf der Änderung des Verzeichnisnamens - oder als akzeptierte Antwort formuliert es so : " Sie aktualisieren müssen und sich verpflichten , eine Datei im Ordner enthalten, aber nicht den Ordner selbst aktualisieren "; All dies wird jedoch in einem übergeordneten Verzeichnis (oder besser gesagt einem Vorfahrenverzeichnis) ausgeführt. Das folgende Befehlszeilenprotokoll zeigt das Problem:

$ cd /tmp
$ svnadmin create myrepo
$ svn co file:///tmp/myrepo myrepo-wc
Checked out revision 0.

$ cd myrepo-wc/
$ mkdir -p dir1/dir2/dir3
$ svn add dir1/
A         dir1
A         dir1/dir2
A         dir1/dir2/dir3

$ svn ci -m 'add dir1/'
Adding         dir1
Adding         dir1/dir2
Adding         dir1/dir2/dir3

Committed revision 1.

$ echo test1 >> dir1/dir2/dir3/test1.txt
$ echo test2 >> dir1/dir2/dir3/test2.txt
$ svn add dir1/
svn: warning: 'dir1' is already under version control
$ svn add dir1/*
svn: warning: 'dir1/dir2' is already under version control
$ svn add dir1/dir2/dir3/*
A         dir1/dir2/dir3/test1.txt
A         dir1/dir2/dir3/test2.txt
$ svn status
A       dir1/dir2/dir3/test2.txt
A       dir1/dir2/dir3/test1.txt
$ svn ci -m 'add dir1/dir2/dir3/*'
Adding         dir1/dir2/dir3/test1.txt
Adding         dir1/dir2/dir3/test2.txt
Transmitting file data ..
Committed revision 2.

$ svn mv dir1/dir2/dir3/test2.txt dir1/dir2/dir3/test2X.txt
A         dir1/dir2/dir3/test2X.txt
D         dir1/dir2/dir3/test2.txt
$ svn status
D       dir1/dir2/dir3/test2.txt
A  +    dir1/dir2/dir3/test2X.txt
$ svn ci -m 'mv dir1/dir2/dir3/test2.txt dir1/dir2/dir3/test2X.txt'
Deleting       dir1/dir2/dir3/test2.txt
Adding         dir1/dir2/dir3/test2X.txt

Committed revision 3.

$ svn status
$ svn mv dir1/dir2/dir3 dir1/dir2/dir3X
A         dir1/dir2/dir3X
D         dir1/dir2/dir3/test2X.txt
D         dir1/dir2/dir3/test1.txt
D         dir1/dir2/dir3
$ svn status
D       dir1/dir2/dir3
D       dir1/dir2/dir3/test2X.txt
D       dir1/dir2/dir3/test1.txt
A  +    dir1/dir2/dir3X
D  +    dir1/dir2/dir3X/test2.txt
$ svn ci -m 'mv dir1/dir2/dir3 dir1/dir2/dir3X'
Deleting       dir1/dir2/dir3
svn: Commit failed (details follow):
svn: Directory '/dir1/dir2/dir3' is out of date
$ svn status
D       dir1/dir2/dir3
D       dir1/dir2/dir3/test2X.txt
D       dir1/dir2/dir3/test1.txt
A  +    dir1/dir2/dir3X
D  +    dir1/dir2/dir3X/test2.txt
$ svn up
   C dir1/dir2/dir3
At revision 3.
Summary of conflicts:
  Tree conflicts: 1

Und so hätte es sein sollen - eine svn upAktion ausführen, nachdem die Datei verschoben / umbenannt wurde; Beachten Sie, wie sich die Versionsnummern svn status -vnach dem svn updateBefehl ändern :

$ cd /tmp
$ rm -rf myrepo*

$ svnadmin create myrepo
$ svn co file:///tmp/myrepo myrepo-wc
Checked out revision 0.

$ cd myrepo-wc/
$ mkdir -p dir1/dir2/dir3
$ svn add dir1/
A         dir1
A         dir1/dir2
A         dir1/dir2/dir3
$ svn ci -m 'add dir1/'
Adding         dir1
Adding         dir1/dir2
Adding         dir1/dir2/dir3

Committed revision 1.

$ echo test1 >> dir1/dir2/dir3/test1.txt
$ echo test2 >> dir1/dir2/dir3/test2.txt
$ svn add dir1/dir2/dir3/*
A         dir1/dir2/dir3/test1.txt
A         dir1/dir2/dir3/test2.txt
$ svn status
A       dir1/dir2/dir3/test2.txt
A       dir1/dir2/dir3/test1.txt
$ svn ci -m 'add dir1/dir2/dir3/*'
Adding         dir1/dir2/dir3/test1.txt
Adding         dir1/dir2/dir3/test2.txt
Transmitting file data ..
Committed revision 2.

$ svn mv dir1/dir2/dir3/test2.txt dir1/dir2/dir3/test2X.txt
A         dir1/dir2/dir3/test2X.txt
D         dir1/dir2/dir3/test2.txt
$ svn status
D       dir1/dir2/dir3/test2.txt
A  +    dir1/dir2/dir3/test2X.txt
$ svn ci -m 'mv dir1/dir2/dir3/test2.txt dir1/dir2/dir3/test2X.txt'
Deleting       dir1/dir2/dir3/test2.txt
Adding         dir1/dir2/dir3/test2X.txt

Committed revision 3.

$ svn status
$ svn status -v
                 0        0  ?           .
                 1        1 username dir1
                 1        1 username dir1/dir2
                 1        1 username dir1/dir2/dir3
                 3        3 username dir1/dir2/dir3/test2X.txt
                 2        2 username dir1/dir2/dir3/test1.txt
$ svn up
At revision 3.
$ svn status -v
                 3        3 username .
                 3        3 username dir1
                 3        3 username dir1/dir2
                 3        3 username dir1/dir2/dir3
                 3        3 username dir1/dir2/dir3/test2X.txt
                 3        2 username dir1/dir2/dir3/test1.txt
$ svn mv dir1/dir2/dir3 dir1/dir2/dir3X
A         dir1/dir2/dir3X
D         dir1/dir2/dir3/test2X.txt
D         dir1/dir2/dir3/test1.txt
D         dir1/dir2/dir3
$ svn status
D       dir1/dir2/dir3
D       dir1/dir2/dir3/test2X.txt
D       dir1/dir2/dir3/test1.txt
A  +    dir1/dir2/dir3X
$ svn ci -m 'mv dir1/dir2/dir3 dir1/dir2/dir3X'
Deleting       dir1/dir2/dir3
Adding         dir1/dir2/dir3X

Committed revision 4.

$ svn status
$ svn status -v
                 3        3 username .
                 3        3 username dir1
                 3        3 username dir1/dir2
                 4        4 username dir1/dir2/dir3X
                 4        4 username dir1/dir2/dir3X/test2X.txt
                 4        4 username dir1/dir2/dir3X/test1.txt
$ svn up
At revision 4.
$ svn status -v
                 4        4 username .
                 4        4 username dir1
                 4        4 username dir1/dir2
                 4        4 username dir1/dir2/dir3X
                 4        4 username dir1/dir2/dir3X/test2X.txt
                 4        4 username dir1/dir2/dir3X/test1.txt

Und wie OP sagte - sollte man vergessen, dies zu tun, svn updatebevor ein neuer Zug / Umbenennen + Festschreiben erfolgt und das "Festschreiben fehlgeschlagen" aufgetreten ist - dann kann man verwenden svn resolve --accept working -R ., um die Festschreibungsaktion beenden zu können.

sdaau
quelle
1

Das hat bei mir funktioniert:

vi someotherfile
...various changes to the other file
svn mv olddir newdir
svn commit -m"Moved olddir out of the way" olddir
svn commit -m"New location of olddir" newdir
svn update
svn commit -m"Changed someotherfile" someotherfile

Ich vermute, dass es verschiedene andere Möglichkeiten gab, und dass es auch den Trick getan hätte, sicherzustellen, dass vor dem svn mv ein sauberes Arbeitsverzeichnis vorhanden war.

xgretsch
quelle
0

Man könnte sich ein Szenario vorstellen, in dem das Verzeichnis von einem anderen Benutzer im Repository geändert wurde. Das Umbenennen desselben Ordners in Ihrer Arbeitskopie kann beim Festschreiben Baumkonflikte auslösen.

Das Lösen von Konflikten zeigt, wie Sie "Baumkonflikte" in Subversion lösen.

Zellus
quelle
Ich bin in einem Einzelentwicklerszenario, in dem keine externen Änderungen auftreten.
Lloeki