web-dev-qa-db-fra.com

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

Je me demandais quelle serait la meilleure approche pour déplacer le code source, avec l'historique, d'un projet d'équipe vers 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 de vouloir passer à un autre projet d'équipe est également motivée par le fait que l'implémentation d'origine (en cours de restauration à partir d'une sauvegarde qui a été maintenue par un tiers) utilisait un modèle de processus tiers que nous ne souhaitons pas utiliser. aller de l'avant. Nous souhaitons commencer à utiliser le suivi des éléments de travail et les rapports une fois la migration terminée.

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

tf.exe déplacer $/ProjectA $/ProjectB

Je crois comprendre que cette commande fonctionne un peu comme une opération de changement de nom, tandis que le déplacement avec l'élément de menu contextuel "Déplacer" dans l'Explorateur de contrôle de code source ressemble plus à une opération de suppression et d'ajout. En outre, le chemin de déplacement tf.exe associerait-il réellement le code sous les dossiers au projet d'équipe approprié, en supposant que $/ProjectA est le dossier de contrôle de la source racine pour un projet et $/ProjectB est le dossier de contrôle de la source racine pour l'autre? L'essentiel est de pouvoir conserver l'histoire, si possible.

Tout conseil ou astuce serait grandement apprécié!

Modifier - La connexion à un autre projet pourrait-elle gérer ce scénario - un peu comme Microsoft le décrit dans la documentation Branching Guidance ? Je pense que cela pourrait être la réponse, car l'histoire serait probablement préservée avec la branche. Cependant, je n'ai pas accès à une instance de Team Foundation Server 2008 pour le moment.

57
Joseph Ferris

Déplacer et renommer sont des alias. Il n'y a absolument aucune différence, quelle que soit la version de TFS, avec la ligne de commande ou 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 la fréquence de changement du nom et/ou du chemin parent. Il n'y a en fait aucun moyen d'obtenir un "faux" changement de nom (supprimer + ajouter) sans beaucoup de travail manuel de votre part.

Cependant, bien que ce modèle de version soit très pur dans un sens théorique, il a quelques pièges pratiques. Parce que différents éléments peuvent occuper le même nom à différents moments, TFS a besoin du nom complet + 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é les éléments du système, si vous dites tf [doSomething] $/newname -version: oldversion alors cela deviendra confus et lancera une erreur ou opérez sur un élément que vous n’avez peut-être pas prévu. Vous devez faire attention à passer des combinaisons valides (newname + newversion ou oldname + oldversion) pour vous assurer que les commandes se comportent comme vous le souhaitez.

TFS 2010 change quelque peu l'histoire: c'est une branche + supprimer sous les couvertures, provoquant le changement de l'ID d'article. Même ainsi, les commandes de tous les jours comme Get et History sont "truquées" très bien; les anciens clients sont compatibles à 95% environ. 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 deviennent ambiguës comme indiqué ci-dessus, le serveur accepte simplement le nom que vous spécifiez et s'exécute avec. Cela améliore les performances globales du système et élimine plusieurs pièges dans lesquels les utilisateurs inconnus sont souvent tombés, au prix de ne pas être aussi flexible et de ne pas conserver l'historique avec une précision de 100% (par exemple, lorsqu'il y a des collisions de noms lors d'une fusion de deux branches).

Revenons au problème en cours ...

Ce n'est pas aussi simple que de dire tf renommer $/projectA $/projectB. Les dossiers de niveau supérieur dans l'arborescence de contrôle des sources sont réservés à l'assistant de création de projet d'équipe; vous ne pouvez pas exécuter de commandes tf standard contre eux. Vous avez besoin d'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 $/ProjectA]

En ce qui concerne les pièges que j'ai mentionnés, je vais en développer un en ce moment car la recherche de l'histoire ancienne vous semble très importante. Une fois que vous avez archivé le changement de nom, tf history $/ProjectA/somefile.cs ne fonctionnera PAS. Par défaut, les commandes tf supposent que version = "latest". Chacune de ces alternatives aura l'historique complet que vous souhaitez:

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

Une dernière alternative à des fins d'exhaustivité et de débogage:

  • tf history $/ProjectA/somefile.cs -slotmode. Vous ne verrez que les changements survenus avant le déménagement; cependant, vous verrez également l'historique de tous les autres éléments pouvant avoir vécu 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 à travers l'histoire comme si c'était en 2008 plutôt qu'en fonction du chemin d'accès.)

EDIT - non, le branchement n'est pas une excellente alternative. Bien que la création de branches laisse suffisamment de métadonnées dans le système pour tracer l'historique complet de et vers ProjectB, elle n'est pas très conviviale en 2008. Prévoyez de passer beaucoup de temps à apprendre la commande tf merges (pas d'équivalent d'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 propre que vous obtiendriez d'un Renommer.

38
Richard Berg

La réponse de Richard ci-dessus est bien écrite et explique bien la situation. Cependant, j'avais quelques astuces plus pratiques à ajouter.

Dans TFS2010, le comportement par défaut fait sembler 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 VS2010) est:

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 de fichier à tout moment. Peut-être que d'autres personnes le voient différemment.

Le premier problème est que l'interface graphique qui apparaît pour moi dans VS2010 en utilisant TFS2010 ne montre initialement que l'historique depuis le déménagement. L'élément le moins récent de la liste est l'opération de renommage. Il peut être développé avec une petite flèche déroulante subtile. En dessous se trouve l'histoire de l'emplacement précédent. Si vous ne savez pas rechercher cela, il peut sembler que votre histoire a disparu.

Le deuxième problème est que si vous supprimez ultérieurement ProjectA (parce que vous avez terminé la migration vers ProjectB, par exemple), l'historique est vraiment parti. Le développement de la liste déroulante dans l'historique de $/ProjectB/somefile.cs ne produit pas l'historique plus ancien.

17
solublefish

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

  • Installez Git-TF à partir du code binaire, Choclatey ou source.

  • Clonez un dossier TFS:

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

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

  • Configurez le nouveau Git Repo pour qu'il se connecte à un dossier vide TFS.

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

  • N'oubliez pas le --deep

git tf pull

Vous devriez recevoir un message à ce stade "git-tf: il s'agit d'un référentiel nouvellement configuré. Il n'y a rien à extraire de tfs."

git commit -a -m "merge commit"

git tf checkin --deep

2
david004

Concernant la commande d'origine ci-dessus: -

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

Les noms source et cible doivent être entourés de guillemets au cas où il y aurait des espaces dans le chemin d'accès complet. J'ai trouvé difficile de le faire sur $ _. ServerItem car l'entourer de d'échappement "renvoie cet objet enfant entier et pas seulement la chaîne .serverItem. Ou si j'ai réussi à obtenir la chaîne, j'ai obtenu retours de chariot indésirables tels que

"
$ proj/dossier/fichier
"

Finalement, j'ai obtenu la commande pour travailler avec les éléments suivants, mais j'ai trouvé que l'historique n'est toujours pas transféré, ce qui était le point essentiel! Je pense donc que cette commande est l'équivalent direct de simplement utiliser un clic droit de la souris dans l'explorateur de source et de sélectionner 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 }

A noter également, il faut utiliser le backtick `pour s'échapper"

0
Philip Beck