2010-10-15 7 views
56

Aunque de alguna manera soy versado en VCS (usuario regular de svn, git y git-svn) no puedo entender este peculiar comportamiento de SVN.Una manera sensata de cambiar el nombre de un directorio en una copia de trabajo de subversión

Cada vez que necesito para cambiar el nombre de un directorio en mi copia de trabajo SVN desde un estado de otra manera 'limpia' - es decir, svn status no devuelve nada y todas las demás modificaciones se han comprometido - como tal (que es lo que sugiere el documento SVN):

svn mv foo bar 
svn commit 

SVN se queja en voz alta:

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

Como usted desee:

svn update 

que da:

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

Hay un conflicto de árbol, mientras que ningún cambio de terceros sucedió. Obviamente, la única manera de salir de este lío conflicto de árbol es genéricamente (del libro rojo SVN):

svn resolve --accept working -R . 
svn commit 

Cambiar el nombre de él de forma remota en el repositorio y luego actualizar mi copia de trabajo parece bastante braindead:

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

¿Existe alguna forma sancionada y simplificada de cambiar el nombre de una carpeta que me falta? ¿Cuál es la causa raíz de ese estado de conflicto de árbol particularmente sorprendente?

+0

¿Se puede publicar el mensaje de conflicto de árbol exacto? –

+0

También he visto este comportamiento antes, pero no estoy seguro de cuál es la causa. ¿Es cuando agregas un directorio y lo renombra antes tal vez? –

+0

También experimento este comportamiento y no he podido encontrar un motivo. Siempre lo he atribuido a "la forma en que SVN funciona". Me vuelve loco. –

Respuesta

56

svn mv funciona para mí:

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> 

Lo siento por la salida sueca de SVN.

Debe haber algo más que sea incorrecto en su caso.

Editar:
Como se señaló en los comentarios por Lloeki

Para reproducir el comportamiento también es necesario actualizar y cometer un archivo contenido en la carpeta, pero no actualizar la propia carpeta.

archivo cometer crea un nuevo rev n en la repo, pero metadatos local no se actualiza (como lo ha estar siempre, ver SVN registro después de cualquier commit), por lo tanto dir metadatos es al rev n- 1. Sigue que svn no confirmará debido a la diferencia de metadatos , y no actualizará porque de hecho existe un conflicto en el directorio: actualización de metadatos contra eliminación.

El comportamiento es "esperado" y la "solución" es actualizar la copia de trabajo antes de emitir el comando svn rename.

+2

Encontrar que 'algo más' es en realidad parte de la pregunta :) Ahora modifique Nuevo documento de texto.txt, confírmelo, luego mv el directorio y vuelva a comprometerlo. – Lloeki

+1

@Lloeki, sí, al modificar el archivo de texto, se reproduce el conflicto del árbol. Realmente me parece un error, ¿ha buscado en el rastreador de problemas en http://subversion.apache.org/ y/o ha presentado un informe de fallas allí? –

+2

Finalmente encontré el motivo, que tiene sentido de una manera subvertida: la confirmación de archivo crea una nueva rev * n * en el repositorio, pero los metadatos locales no se actualizan (como siempre ha sido, ver 'svn log' después de cualquier confirmación) , por lo tanto, los metadatos dir están en rev * n-1 *. Se deduce que svn no se comprometerá debido a la diferencia de metadatos, y no se actualizará porque de hecho hay un conflicto en el directorio: actualización de metadatos contra eliminación. – Lloeki

0

Podría pensarse en un escenario en el que el directorio ha sido cambiado en el repositorio por otro usuario. Renombrar la misma carpeta en su copia de trabajo puede desencadenar conflictos de árbol durante la confirmación.

Resolving conflicts muestra cómo resolver 'conflictos de árbol' en subversión.

+0

Estoy en un escenario de desarrollador solitario donde no ocurre ningún cambio externo. – Lloeki

1

Esto funcionó para mí:

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 

sospecho que había varias otras maneras posibles redonda, y que asegura hubo un directorio de trabajo limpio antes de hacer el svn mv también habría hecho el truco.

7

OK, me encontré con esto - y finalmente puedo reconstruir el problema con una simple sesión de terminal: el problema ocurre si svn mv (mover/renombrar) un archivo; luego cometer ese cambio; entonces (sin haciendo un svn update primero), svn mv el directorio padre del archivo cuya mover/cambiar el nombre de antes era comprometido - y, finalmente, hacer una svn commit en el cambio del nombre del directorio - o como accepted answer pone: "también necesita actualizar y confirmar un archivo contenido en la carpeta, pero no actualizar la carpeta en sí "; pero todo esto se ejecuta en un directorio padre (o más bien, ancestro). Aquí hay registro de línea de comandos que demuestra el problema:

$ 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 

Y esto es lo que debería haber sido - haciendo un svn up después de que el archivo de mover/renombrar fue comitted; observar cómo los números de versión que indica svn status -v cambio después del comando svn update:

$ 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 

Y como dijo OP - hay que olvidar que hacer el svn update antes de que un nuevo movimiento/renombrar + cometer, y el "fallido Commit" ocurrido - entonces uno puede usar svn resolve --accept working -R . para poder finalizar la acción de compromiso.

Cuestiones relacionadas