Version control Team Foundation服务器-具有历史记录的移动源

Version control Team Foundation服务器-具有历史记录的移动源,version-control,tfs,Version Control,Tfs,我想知道在将源代码和历史从一个团队项目移动到另一个团队项目时,最好的方法是什么。我不关心工作项、报告或SharePoint网站,因为我们将从中恢复的系统没有使用这些功能。希望转移到另一个团队项目的原因还在于,原始实现(从第三方维护的备份中恢复)使用了我们不希望继续使用的第三方流程模板。我们希望在迁移完成后开始使用工作项跟踪和报告 这似乎是一种可能的情况。根据文档,它可用于更改流程模板。但是,我很好奇tf.exe move语法是否有效?比如: tf.exe move$/ProjectA$/Proj

我想知道在将源代码和历史从一个团队项目移动到另一个团队项目时,最好的方法是什么。我不关心工作项、报告或SharePoint网站,因为我们将从中恢复的系统没有使用这些功能。希望转移到另一个团队项目的原因还在于,原始实现(从第三方维护的备份中恢复)使用了我们不希望继续使用的第三方流程模板。我们希望在迁移完成后开始使用工作项跟踪和报告

这似乎是一种可能的情况。根据文档,它可用于更改流程模板。但是,我很好奇tf.exe move语法是否有效?比如:

tf.exe move$/ProjectA$/ProjectB

据我所知,该命令的操作非常类似于重命名操作,而在源代码管理资源管理器中使用“移动”上下文菜单项进行移动更像是删除和添加操作。另外,假设$/ProjectA是一个项目的根源代码管理文件夹,而$/ProjectB是另一个项目的根源代码管理文件夹,那么tf.exe移动路径是否会将文件夹下的代码与相应的团队项目相关联?如果可能的话,关键是能够保存历史

任何建议或提示将不胜感激


编辑-分支到另一个项目可以处理这种情况吗-就像Microsoft在文档中讨论的那样?我认为这可能是答案,因为历史很可能会与分支一起保存。但是,目前我无法访问Team Foundation Server 2008实例来测试它。

< P>移动和重命名是别名。在任何版本的TFS中,与命令行或UI完全没有区别

它们都保存着历史。至少在2005/2008年,无论名称和/或父路径更改的频率或幅度有多大,都会在VersionedItem表中保留相同的物理项。实际上,如果没有大量的手工工作,就无法获得“假”重命名(删除+添加)

然而,尽管这个版本控制模型在理论上非常纯粹,但它也存在一些实际问题。因为不同的项目可以在不同的时间点使用相同的名称,所以TFS需要全名+版本来唯一标识您发送给它的任何输入。通常你不会注意到这个限制,但是一旦你重命名了系统中的项目,如果你说tf[doSomething]$/newname-version:oldversion,那么它就会变得混乱,或者抛出错误,或者对你可能不想要的项目进行操作。您必须小心地传递有效的组合(newname+newversion或oldname+oldversion),以确保命令按您想要的方式运行

TFS2010在某种程度上改变了这个故事:它是一个分支+封面下的删除,导致itemID发生变化。即便如此,Get和History等日常命令都是“伪造”得很好的;老客户机的兼容性约为95%。优点是,当您在系统中有多个重命名,并且基于路径的项查找开始变得不明确(如上所述),服务器将只接受您指定的名称并使用它运行。这提高了整体系统性能,消除了不熟悉用户经常陷入的几个陷阱,但代价是不够灵活,无法以100%的精度保存历史(例如,在两个分支合并过程中出现名称冲突时)

回到手头的问题

这并不是说tf rename$/projectA$/projectB那么简单。源代码管理树中的顶级文件夹是为团队项目创建向导保留的;您不能对它们运行标准tf命令。您需要的脚本如下:

Get-TfsChildItem $/ProjectA |
    select -Skip 1 |  # skip the root dir
    foreach {
        tf rename $_.serveritem $_.serveritem.replace("$/ProjectA", "$/ProjectB")
    }
[当然,如果在$/ProjectA下没有太多子项,您可以手工完成]

至于我提到的哥特加,我现在将详细说明一个,因为查找古老的历史对你来说似乎非常重要。签入重命名后,tf history$/ProjectA/somefile.cs将不起作用。默认情况下,tf命令假定version=“latest.”这些选项中的任何一个都将显示您想要的完整历史记录:

  • tf history$/ProjectA/somefile.cs;1234变更集1234在移动前的位置
  • tf history$/ProjectB/somefile.cs;5678移动后变更集5678所在的位置。或者你可以省略这个版本
出于完整性和调试目的的最终备选方案:

  • tf history$/ProjectA/somefile.cs-slotmode。您将只看到移动之前发生的更改;但是,您还将看到在移动到B下方的项目之前或之后,$/ProjectA/somefile.cs“slot”中可能存在的任何其他项目的历史记录
(在TFS 2010中,“插槽模式”是默认行为;有一个-ItemMode选项,用于请求在历史记录中跟踪您的查找,就像2008年一样,而不是基于路径。)


编辑-不,分支不是一个很好的选择。虽然分支确实在系统中留下了足够的元数据来跟踪ProjectB的完整历史记录,但在2008年,它对用户的友好程度并不高。计划花费大量时间学习tf merges命令(没有等效的UI)。2010极大地提高了您跨多个分支可视化更改的能力,但它仍然不是您从重命名中获得的干净统一的体验。

上面Richard的回答写得很好,并且很好地解释了这种情况。然而,我确实有一些更实际的问题需要补充

在TFS2010中,默认行为使其看起来像移动文件会导致您丢失移动之前的所有历史记录。我的用户的命令
tf history $/ProjectB/somefile.cs
Get-TfsChildItem $/ProjectA |
select -Skip 1 |  # skip the root dir
foreach {
    tf rename $_.serveritem $_.serveritem.replace("$/ProjectA", "$/ProjectB")
}
$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 }