移动和重命名是别名。无论是命令行还是 UI,在任何版本的 TFS 中都绝对没有区别。
它们都保留了历史。至少在 2005/2008 年,您在 VersionedItem 表中保留相同的物理项,无论名称和/或父路径更改的频率或剧烈程度如何。实际上,如果您不进行大量手动工作,就无法获得“假”重命名(删除 + 添加)。
然而,虽然这种版本控制模型在理论上非常纯粹,但它也存在一些实际问题。因为不同的项目可以在不同的时间点占用相同的名称,所以 TFS 需要全名 + 版本来唯一标识你发送给它的任何输入。通常你不会注意到这个限制,但是一旦你在系统中重命名了项目,如果你说 tf [doSomething] $/newname -version:oldversion 那么它会混淆并抛出错误或对您可能不想要的项目进行操作。您必须小心传递有效的组合(新名称+新版本或旧名称+旧版本)以确保命令按照您想要的方式运行。
TFS 2010 在某种程度上改变了故事:它是一个分支+删除幕后,导致 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 历史 $/ProjectA/somefile.cs -slotmode。您只会看到移动之前发生的变化;但是,您还会看到在您移动到 B 下方的项目之前或之后可能存在于 $/ProjectA/somefile.cs“槽”中的任何其他项目的历史记录。
(在 TFS 2010 中,“槽模式”是默认行为;有一个 -ItemMode 选项可请求像 2008 年那样跨历史跟踪您的查找,而不是基于路径。)
编辑 - 不,分支不是一个很好的选择。虽然分支确实在系统中留下了足够的元数据来追踪与 ProjectB 之间的完整历史记录,但在 2008 年它的用户友好性并不高。计划花大量时间学习 tf merges 命令(没有等效的 UI )。 2010 显着提高了您在多个分支中可视化更改的能力,但它仍然不是您从重命名中获得的干净统一的体验。