Team Foundation Server – Source en mouvement avec 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 à partir de ces fonctionnalités n’a pas été utilisé. La raison de vouloir passer à un autre projet d’équipe est également due au fait que l’implémentation d’origine (restaurée à partir d’une sauvegarde gérée 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 et le reporting des éléments de travail une fois la migration terminée.

La plate-forme d’intégration TFS semble être un scénario probable. Selon la documentation, il peut être utilisé pour modifier le modèle de processus. Cependant, j’étais curieux de savoir si la syntaxe tf.exe move pouvait fonctionner? Quelque chose comme:

tf.exe move $ / ProjectA $ / ProjectB

Je crois comprendre que cette commande fonctionne comme une opération de renommage, tandis que le déplacement avec l’élément de menu contextuel “Déplacer” dans l’Explorateur de contrôle de code source est 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 source racine d’un projet et $ / ProjectB le dossier de contrôle de source racine? L’essentiel est de pouvoir conserver l’historique, si possible.

Des conseils ou des astuces seraient grandement appréciés!

Modifier – Le twigment à un autre projet peut-il gérer ce scénario – un peu comme Microsoft l’explique dans la documentation du guide de twigment ? Je pense que cela pourrait être la réponse, puisque l’histoire serait probablement préservée avec la twig. Cependant, je n’ai pas access à une instance Team Foundation Server 2008 pour le tester.

Move et Rename sont des alias. Il n’y a absolument aucune différence, dans aucune version de TFS, à partir de la ligne de commande ou de l’interface utilisateur.

Les 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 et la fréquence de modification du nom et / ou du chemin parent. Il n’y a aucun moyen d’obtenir un “faux” renommer (supprimer + append) sans beaucoup de travail manuel de votre part.

Cependant, même si ce modèle de contrôle de version est très pur sur le plan théorique, il comporte des pièges pratiques. Étant donné que différents éléments peuvent occuper le même nom à différents moments, TFS a besoin du nom complet + de la version pour identifier de manière unique les entrées que vous lui envoyez. Normalement, vous ne remarquez pas cette ressortingction, mais une fois que vous avez renommé des éléments dans le système, si vous dites tf [doSomething] $ / newname -version: oldversion, il sera confus et provoquera une erreur ou fonctionnera sur un élément pas voulu. 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: il s’agit d’une twig + supprimer sous les couvertures, ce qui entraîne la modification de l’ID d’élément. Malgré cela, les commandes quotidiennes telles que Get et History sont très bien simulées. les anciens clients sont compatibles à environ 95%. L’avantage est que lorsque vous avez plusieurs renoms dans le système et que les recherches d’éléments basées sur des chemins commencent à devenir ambiguës, comme mentionné ci-dessus, le serveur accepte simplement le nom que vous spécifiez et que vous utilisez. Cela améliore les performances globales du système et élimine plusieurs pièges dans lesquels les utilisateurs peu familiers tombent souvent, au prix de ne pas être aussi flexibles et de ne pas conserver l’historique avec une précision de 100% (par exemple, lors de collisions de deux twigs).

Revenons au problème à scope de main …

Ce n’est pas aussi simple que de dire tf renommer $ / projectA $ / projectB . Les dossiers de niveau supérieur de l’arborescence du contrôle de code 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 $ / ProjectA]

En ce qui concerne les pièges que j’ai mentionnés, je vais en développer une en ce moment car la recherche de la vieille histoire vous semble très importante. Une fois l’archive renommée, tf history $ / ProjectA / somefile.cs ne fonctionnera PAS. Par défaut, les commandes tf supposent version = “latest”. Chacune de ces alternatives sera l’histoire complète que vous voulez:

  • tf historique $ / ProjectA / somefile.cs; 1234 où changeset 1234 était avant le déplacement
  • tf historique $ / ProjectB / somefile.cs; 5678 où changeset 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 historique $ / ProjectA / somefile.cs -slotmode . Vous ne verrez que les changements qui ont eu lieu avant le déménagement; Cependant, vous verrez également l’historique de tout autre élément ayant 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 par défaut est le mode “slot”; il existe une option -ItemMode pour demander que votre recherche soit retracée dans l’historique, comme c’était le cas en 2008 plutôt que sur les chemins).

EDIT – non, les twigments ne sont pas une excellente alternative. Bien que le twigment laisse suffisamment de métadonnées dans le système pour retracer l’historique complet de & vers ProjectB, il n’est pas très convivial en 2008. Prévoyez de passer beaucoup de temps à apprendre la commande tf merges (sans équivalent d’interface utilisateur). 2010 améliore considérablement votre capacité à visualiser les changements sur plusieurs twigs, mais ce n’est toujours pas l’expérience unifiée que vous obtiendriez d’un Rename.

La réponse de Richard ci-dessus est bien écrite et explique bien la situation. J’ai cependant eu quelques problèmes pratiques à append.

Dans TFS2010, le comportement par défaut donne l’ impression que le déplacement d’un fichier vous fait perdre tout l’historique 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 l’historique de somefile.cs, à la fois avant et après le déménagement. Ils veulent “l’historique du code actuellement stocké dans $ / ProjectB / somefile.cs”, quel que soit le nom de fichier à un moment donné. Peut-être que d’autres personnes le voient différemment.

La première est que l’interface graphique qui apparaît pour moi dans VS2010 en utilisant TFS2010 ne montre que l’historique depuis le déménagement. L’élément le moins récent dans la liste est l’opération renommer. Il peut être étendu avec une petite flèche déroulante subtile. En dessous se trouve l’historique de l’emplacement précédent. Si vous ne savez pas chercher cela, cela peut sembler avoir perdu votre histoire.

Le second piège est que si vous supprimez plus tard ProjectA (parce que vous avez terminé la migration vers ProjectB, par exemple), l’historique a vraiment disparu. L’extension du menu déroulant de l’historique pour $ / ProjectB / somefile.cs ne produit pas l’historique le plus ancien.

Une autre option (et je pense plus facile) consiste à importer dans Git puis à exporter vers TFS à l’ aide des outils de ligne de commande Git-TF .

  • Installez Git-TF à partir de code binary, choclatey ou source.

  • Cloner un dossier TFS:

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

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

  • Configurez le nouveau Git Repo pour vous connecter à un dossier TFS vide .

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

  • N’oublie pas le --deep

git tf pull

Vous devriez avoir un message à ce stade “git-tf: ceci est un repository nouvellement configuré. Il n’y a rien à récupérer de tfs.”

git commit -a -m "merge commit"

git tf checkin --deep

En ce qui concerne 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 source et cible doivent être entourés de guillemets au cas où il y aurait des espaces dans le chemin d’access complet. J’ai eu du mal à faire cela sur $ _. ServerItem comme entourant avec escaped “renvoie cet object enfant entier et pas seulement la chaîne .serverItem. Ou si j’ai réussi à obtenir la chaîne, j’ai eu des retours de chariot indésirables tels que


$ proj / dossier / fichier

Finalement, j’ai eu la commande pour travailler avec ce qui suit, mais j’ai trouvé que l’histoire n’est toujours pas transférée, ce qui était le but! Donc, je crois que cette commande est l’équivalent direct d’un simple clic de la souris dans l’explorateur de sources et que vous sélectionnez l’option Renommer (ou déplacer).

 $tfsServerSsortingng = "http://machine:8080/tfs/DefaultCollection" $tfs = Get-TfsServer $tfsServerSsortingng 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 s’échapper»