Une manière sensée de renommer un répertoire dans la copie de travail de subversion

Bien que quelque peu versé dans VCS (utilisateur régulier de svn, git et git-svn), je n’arrive pas à comprendre ce comportement particulier de SVN.

Chaque fois que j’ai besoin de renommer un répertoire dans ma copie de travail SVN à partir d’un état “propre” – c’est-à-dire que svn status ne retourne rien et toutes les autres modifications ont été validées – comme le suggère svn doc:

 svn mv foo bar svn commit 

SVN se plaint bruyamment:

 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 de tierce partie n’est survenu . De toute évidence, la seule façon de sortir de ce désordre de conflit d’arbre est génériquement (du svn red book):

 svn resolve --accept working -R . svn commit 

En le renommant à distance sur le repo puis en mettant à jour ma copie de travail semble tout à fait braindead:

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

Existe-t-il un moyen sanctionné, plus simple de renommer un dossier qui me manque? Quelle est la cause profonde de cet état de conflit particulièrement surprenant?

svn mv fonctionne 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 autre chose qui ne va pas dans votre cas.

Modifier:
Comme souligné dans les commentaires de Lloeki

Pour reproduire le comportement, vous devez également mettre à jour et valider un fichier contenu dans le dossier, mais ne pas mettre à jour le dossier lui-même.

le commit de fichier crée une nouvelle rev n sur le repository, mais les métadonnées locales ne sont pas mises à jour (comme cela a toujours été le cas, voir svn log après tout commit), donc les métadonnées dir sont à rev n-1. Il s’ensuit que svn ne sera pas validé à cause du diff des métadonnées, et qu’il ne sera pas mis à jour car il y a effectivement un conflit sur le répertoire: metadata update vs delete.

Le comportement est “attendu” et la “solution” consiste à mettre à jour la copie de travail avant d’émettre la commande svn rename .

OK, je suis tombé sur ceci – et je peux enfin reconstruire le problème avec une simple session de terminal: le problème arrive si vous svn mv (move / rename) un fichier; puis commettez ce changement; alors ( sans faire une svn update premier), svn mv le répertoire parent du fichier dont le move / rename a été précédemment validé – et enfin un svn commit sur le changement du nom du répertoire – ou comme réponse acceptée le dit: ” vous aussi besoin de mettre à jour et de valider un fichier contenu dans le dossier, mais pas de mettre à jour le dossier lui-même “; mais tout cela est exécuté dans un répertoire parent (ou plutôt ancêtre). Voici un 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 cela aurait dû être fait – faire un svn up après que le déplacement / renommage du fichier ait été créé; Notez comment les numéros de version rapportés par svn status -v changent après la commande 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 

Et comme OP a dit – devrait-on oublier de faire la svn update avant un nouveau déplacer / renommer + commit, et le “Commit failed” s’est produit – alors on peut utiliser svn resolve --accept working -R . pour pouvoir terminer l’action de validation.

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 solutions possibles, et que le fait de disposer d’un répertoire de travail propre avant de faire le svn mv aurait également fait l’affaire.

On pourrait penser à un scénario où 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ésoudre les conflits montre comment résoudre les «conflits d’arbres» dans la subversion.