57 votes

Team Foundation Server - Déplacer la source avec l'historique

Je me demandais quelle serait la meilleure approche pour déplacer le code source, avec son historique, d'un projet d'équipe à un autre projet d'équipe. Je ne suis pas concerné par les éléments de travail, les rapports ou les sites SharePoint, car le système que nous allons restaurer n'utilisait pas ces fonctionnalités. La raison pour laquelle nous voulons passer à un autre projet d'équipe est également motivée par le fait que la mise en œuvre originale (restaurée à partir d'une sauvegarde maintenue par un tiers) utilisait un modèle de processus tiers que nous ne souhaitons pas utiliser à l'avenir. Nous voulons commencer à utiliser le suivi des éléments de travail et les rapports une fois la migration terminée.

El Plate-forme d'intégration TFS semble être un scénario probable. Il peut être utilisé pour changer le modèle de processus, selon la documentation. Cependant, j'étais curieux de savoir si la syntaxe de déplacement de tf.exe pouvait fonctionner ? Quelque chose comme :

tf.exe move $/ProjectA $/ProjectB

Je crois comprendre que cette commande fonctionne comme une opération de renommage, alors que le déplacement avec l'élément de menu contextuel "Move" dans l'explorateur de contrôle de source ressemble davantage à une opération de suppression et d'ajout. En outre, le chemin de déplacement de tf.exe associe-t-il réellement le code sous les dossiers avec le projet d'équipe approprié, en supposant que $/ProjetA est le dossier de contrôle de source racine pour un projet et $/ProjetB est le dossier de contrôle de source racine pour l'autre ? L'essentiel est de pouvoir préserver l'historique, si possible.

Tous les conseils ou astuces seraient grandement appréciés !

Édition - Le fait de passer à un autre projet pourrait-il permettre de gérer ce scénario - un peu comme Microsoft l'explique dans le document intitulé Conseils de branchement de la documentation ? Je pense que cela pourrait être la réponse, puisque l'historique serait probablement conservé avec la branche. Cependant, je n'ai pas accès à une instance de Team Foundation Server 2008 pour le moment pour le tester.

38voto

Richard Berg Points 14218

Déplacer et Renommer sont des alias. Il n'y a absolument aucune différence, dans toutes les versions de TFS, que ce soit en ligne de commande ou dans l'interface utilisateur.

Tous deux préservent l'histoire. Au moins en 2005/2008, vous conservez le même élément physique dans la table VersionedItem, quelle que soit la fréquence ou l'ampleur des changements de nom et/ou de chemin parent. Il n'y a en fait aucun moyen d'obtenir un "faux" renommage (supprimer + ajouter) sans un travail manuel important de votre part.

Toutefois, si ce modèle de versionnement est très pur d'un point de vue théorique, il présente quelques inconvénients pratiques. Parce que différents éléments peuvent occuper le même nom à différents moments, TFS a besoin du nom complet + la version pour identifier de manière unique toutes les entrées que vous lui envoyez. Normalement, vous ne remarquez pas cette restriction, mais une fois que vous avez renommé des éléments dans le système, si vous dites tf [doSomething] $/newname -version:oldversion alors il sera confus et lancera une erreur ou opérera sur un élément que vous n'avez peut-être pas prévu. Vous devez faire attention à passer des combinaisons valides (nouveau nom+nouvelle version ou ancien nom+ancienne version) pour vous assurer que les commandes se comportent comme vous le souhaitez.

TFS 2010 change quelque peu l'histoire : il s'agit d'une branche+suppression sous la couverture, ce qui entraîne un changement de l'itemID. Malgré cela, les commandes quotidiennes comme Get et History sont très bien "simulées" ; les anciens clients sont compatibles à 95%. L'avantage est que lorsque vous avez plusieurs renommages dans le système et que les recherches d'éléments basées sur le chemin d'accès commencent à devenir ambiguës comme indiqué ci-dessus, le serveur acceptera simplement le nom que vous spécifiez et fonctionnera avec. Cela améliore les performances globales du système et élimine plusieurs pièges dans lesquels les utilisateurs peu familiers tombaient souvent, au prix de ne pas être aussi flexible et de ne pas préserver l'historique avec une précision de 100% (par exemple lorsqu'il y a des collisions de noms pendant une fusion de deux branches).

Pour en revenir au problème qui nous occupe...

Ce n'est pas aussi simple que de dire tf renommer $/projetA $/projetB . Les dossiers de niveau supérieur dans l'arbre de contrôle de la source sont réservés à l'assistant de création de projet d'équipe ; vous ne pouvez pas exécuter les commandes tf standard contre eux. Ce dont vous avez besoin est un script comme :

Get-TfsChildItem $/ProjectA |
    select -Skip 1 |  # skip the root dir
    foreach {
        tf rename $_.serveritem $_.serveritem.replace("$/ProjectA", "$/ProjectB")
    }

[bien sûr, vous pouvez le faire à la main s'il n'y a pas trop d'enfants sous $/ProjetA].

En ce qui concerne les écueils que j'ai mentionnés, je vais m'étendre sur l'un d'entre eux puisque la recherche de l'histoire ancienne semble très importante pour vous. Une fois que vous avez vérifié le changement de nom, tf historique $/ProjectA/somefile.cs ne fonctionnera PAS. Par défaut, les commandes tf supposent que la version = "latest". N'importe laquelle de ces alternatives vous donnera l'historique complet que vous voulez :

  • tf history $/ProjectA/somefile.cs;1234 où le changeset 1234 était avant le déplacement
  • tf history $/ProjectB/somefile.cs;5678 où le changeset 5678 était après le déplacement. Ou vous pouvez simplement omettre la version.

Une dernière alternative pour des raisons d'exhaustivité et de débogage :

  • tf history $/ProjectA/somefile.cs -slotmode . Vous ne verrez que les changements qui ont eu lieu avant le déplacement ; cependant, vous verrez également l'historique de tous les autres éléments qui ont pu vivre dans le "slot" $/ProjectA/somefile.cs avant ou après l'élément que vous avez déplacé sous B.

(Dans TFS 2010, le "mode slot" est le comportement par défaut ; il y a une option -ItemMode pour demander que votre recherche soit tracée dans l'historique comme en 2008 plutôt que basée sur le chemin).

EDIT - non, le branchement n'est pas une bonne alternative. Bien que le branchement laisse suffisamment de métadonnées dans le système pour retracer l'historique complet vers et depuis le Projet B, il n'est pas terriblement convivial en 2008. Prévoyez de passer beaucoup de temps à apprendre le tf fusionne (sans équivalent dans l'interface utilisateur). 2010 améliore considérablement votre capacité à visualiser les changements sur plusieurs branches, mais ce n'est toujours pas l'expérience unifiée et propre que vous obtiendriez avec un Renommer.

17voto

solublefish Points 591

La réponse de Richard ci-dessus est bien écrite et explique bien la situation. J'ai cependant quelques autres écueils pratiques à ajouter.

Dans TFS2010, le comportement par défaut fait qu'il est semblent comme déplacer un fichier vous fait perdre tout l'historique d'avant le déplacement. La commande que mes utilisateurs sont susceptibles d'utiliser (et celle utilisée, semble-t-il, par l'interface graphique de VS2010) est la suivante :

tf history $/ProjectB/somefile.cs

Mes utilisateurs ont l'intention d'obtenir tout l'historique de somefile.cs, avant et après le déménagement. Ils veulent "l'historique du code qui est actuellement stocké dans $/ProjectB/somefile.cs", quel que soit le nom du fichier à un moment donné. Peut-être que d'autres personnes voient les choses différemment.

Le premier problème est que l'interface graphique qui s'affiche dans VS2010 en utilisant TFS2010 ne montre initialement que l'historique depuis le déplacement. L'élément le moins récent de la liste est l'opération de renommage. Il peut être développé à l'aide d'une subtile petite flèche déroulante. En dessous se trouve l'historique de l'emplacement précédent. Si vous ne savez pas où chercher, vous pouvez avoir l'impression que votre historique a disparu.

Le deuxième problème est que si vous supprimez ultérieurement le projet A (parce que vous avez terminé la migration vers le projet B, par exemple), l'historique disparaît réellement. L'expansion de la liste déroulante dans l'historique pour $/ProjectB/somefile.cs ne produit pas l'ancien historique.

2voto

david004 Points 1310

Une autre option (et je pense plus facile) est d'importer vers Git puis de ré-exporter vers TFS en utilisant le Git-TF outils de ligne de commande.

  • Installer Git-TF à partir d'un code binaire, d'un code Choclatey ou d'un code source.

  • Clonez un dossier TFS :

git tf clone https://myAcc.visualstudio.com/mycollection $/TeamProjectA/Main --deep

  • Désassociez le Repo Git du serveur TFS en supprimant le fichier .Git/tf et le dossier .Git/git-tf fichier.

  • Configurer le nouveau Repo Git pour qu'il se connecte à un site Web. vide Dossier TFS.

git tf configure https://myAcc.visualstudio.com/mycollection $/TeamProjectB/Main --deep

  • N'oubliez pas le --deep

git tf pull

Vous devriez obtenir un message à ce stade "git-tf : this is a newly configured repository. Il n'y a rien à récupérer de tfs".

git commit -a -m "merge commit"

git tf checkin --deep

0voto

Philip Beck Points 41

Concernant la commande originale ci-dessus :-

Get-TfsChildItem $/ProjectA |
select -Skip 1 |  # skip the root dir
foreach {
    tf rename $_.serveritem $_.serveritem.replace("$/ProjectA", "$/ProjectB")
}

Les noms de la source et de la cible doivent être entourés de guillemets au cas où le nom du chemin complet contiendrait des espaces. J'ai trouvé difficile de faire cela sur $_.ServerItem car le fait de l'entourer de " échappés " renvoie l'objet enfant entier et pas seulement la chaîne .serverItem. Ou bien, si je parvenais à obtenir la chaîne de caractères, j'obtenais des retours chariot indésirables tels que

"
$proj/folder/file
"

Finalement, j'ai réussi à faire fonctionner la commande avec ce qui suit, mais j'ai constaté que l'historique n'est toujours pas transféré, ce qui était le but recherché ! Je pense donc que cette commande est l'équivalent direct d'un simple clic droit dans l'explorateur de sources et de la sélection de renommer (ou déplacer).

$tfsServerString = "http://machine:8080/tfs/DefaultCollection"
$tfs = Get-TfsServer $tfsServerString
Get-TfsChildItem -server $tfs "$/Dest Project/MyTestProject" | select -Skip 1 | foreach { $sourceName = $_.serveritem; $targetName = $_.serveritem.replace("$/Dest Project/MyTestProject/", "$/Dest Project/Source/StoreControllers/dSprint/dSprint2/") ; ./tf rename `"$sourceName`" `"$targetName`" /login:myUser }

Notez également qu'il faut utiliser le backtick ` pour échapper à "

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X