web-dev-qa-db-fra.com

Un moyen sain de renommer un répertoire dans la copie de travail de Subversion

Bien que connaissant VCS (utilisateur régulier de svn, git et git-svn), je n'arrive pas à comprendre ce comportement singulier de SVN.

Chaque fois que je dois renommer un répertoire de ma copie de travail SVN à partir d'un état "propre" - c'est-à-dire svn status ne renvoie rien et toutes les autres modifications ont été validées - comme tel (ce que suggère le document svn):

svn mv foo bar
svn commit

SVN se plaint fort:

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

Comme vous le souhaitez:

svn update

Qui donne:

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

Il y a un conflit d'arbre, alors qu'aucun changement tiers n'a eu lie. De toute évidence, le seul moyen de sortir de ce désordre conflictuel est génériquement (d'après le livre rouge svn):

svn resolve --accept working -R .
svn commit

Renommer à distance sur le référentiel puis mettre à jour ma copie de travail me semble tout à fait inutile:

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

Existe-t-il un moyen plus rationalisé et approuvé de renommer un dossier qui me manque? Quelle est la cause fondamentale de cet état de conflit de l’arbre particulièrement surprenant?

67
Lloeki

svn mv travaille pour moi:

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>

Désolé pour la sortie suédoise de svn.

Il doit y avoir quelque chose d'autre qui ne va pas dans votre cas.

Edit:
Comme indiqué dans les commentaires de Lloeki

Pour reproduire le problème, vous devez également mettre à jour et valider un fichier contenu dans le dossier, sans mettre à jour le dossier lui-même.

file commit crée une nouvelle révision sur le référentiel, mais les métadonnées locales ne sont pas mises à jour (comme cela a toujours été le cas, reportez-vous à svn log après toute validation), ainsi les métadonnées dir sont à la révision n-1. Il s'ensuit que svn ne s'engagera pas à cause des différences de métadonnées et qu'il ne se mettra pas à jour car il y a effectivement un conflit dans le répertoire dir: metadata update vs delete.

Le comportement est "attendu" et la "solution" consiste à mettre à jour la copie de travail avant d'émettre le svn rename commande.

68
Albin Sunnanbo

OK, je me suis heurté à cela - et je peux enfin reconstruire le problème avec une simple session de terminal: le problème se produit si vous svn mv (déplacer/renommer) un fichier; alors engagez ce changement; then ( sans faire un svn update première), svn mv le répertoire parent du fichier dont le déplacement/changement de nom a déjà été validé - et enfin faire un svn commit lors de la modification du nom du répertoire - ou comme réponse acceptée le dit: " vous devez également mettre à jour et valider un fichier contenu dans le dossier, mais pas mettre à jour le dossier lui-même "; mais tout cela est exécuté dans un répertoire parent (ou plutôt, ancêtre). Voici le journal de ligne de commande démontrant le problème:

$ 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

Et voici comment il aurait dû être - faire un svn up après que le fichier soit déplacé/renommé; notez comment les numéros de version rapportés par svn status -v changement après le svn update commande:

$ 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

Et comme l’a dit OP - faut-il oublier de faire le svn update avant un nouveau déplacement/changement de nom + commit, et que le "commit échoué" se soit produit - on peut alors utiliser svn resolve --accept working -R . pour pouvoir terminer l'action commit.

8
sdaau

Cela a fonctionné pour moi:

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

Je soupçonne qu'il y avait plusieurs autres moyens possibles et qu'avoir un répertoire de travail propre avant de faire la commande svn mv aurait également fait l'affaire.

1
xgretsch

On pourrait penser à un scénario dans lequel le répertoire a été modifié dans le référentiel par un autre utilisateur. Renommer le même dossier dans votre copie de travail peut déclencher des conflits d'arborescence lors de la validation.

Résolution des conflits montre comment résoudre les "conflits d'arborescence" dans Subversion.

0
zellus