TFS文件夹 - 让它们像Subversion"Trunk/Tags/Branches"一样工作

Sam*_*tte 13 svn tfs

我最近开始使用Team Foundation Server,并且在按照我希望的方式工作时遇到了一些麻烦.

我已经使用Subversion几年了,并且喜欢它的工作方式.我总是在每个项目下设置三个文件夹,Trunk,Tags和Branches.

当我在处理项目时,我的所有代码都位于名为"C:\ dev\projectname"的文件夹下.可以使用Subversion(使用switch命令)将此"projectname"文件夹指向trunk或任何分支或标记.

现在我正在使用TFS(我的客户端系统),我希望事情以同样的方式工作.我用我的项目创建了一个"Trunk"文件夹,并将"Project/Trunk/Website"映射到"c:\ dev\Website".

现在,我想在"tags"文件夹下找到一个版本(位于"Project/Tags/Version 1.0/Website"中,当我执行branch命令时TFS给出了以下错误:

"$ Project/tags/Version 1.0/Website没有适当的映射"

根据我在互联网上可以找到的内容,TFS希望您在项目的根目录(我的案例中为"Project"文件夹)中映射到您的硬盘驱动器,然后将所有源代码放在trunk,标签中和分支都拉到你的硬盘上.这很糟糕,因为它需要在你的硬盘驱动器上有太多东西,更糟糕的是,当你在Visual Studio中使用解决方案时,你将无法下载"2.0版"并将所有项目引用到其他项目工作,因为它们都将指向主文件夹下的"trunk"文件夹,而不仅仅是主文件夹本身.

我想要做的是在我的硬盘上有根"Project/Website"文件夹,并且能够让它指向(映射到)标签,分支或主干,这取决于我正在做什么,而不是通过修复Visual Studio项目引用来解决问题.

想法?

Ric*_*erg 36

首先要理解的是版本树的TFS模型与您可能习惯的不同.它处于频谱的极端.‡

我已经使用Subversion几年了,并且喜欢它的工作方式.我总是在每个项目下设置三个文件夹,Trunk,Tags和Branches.

您认为"标签,分支和中继"的所有内容都由TFS中的文件夹表示."trunk"是由简单添加创建的文件夹,而不是另一个文件夹的分支."分支"是通过分支和合并操作从系统中其他位置派生(以后与之相关)的文件夹.TFS本身没有"标签"; 最接近的模拟是基于历史版本创建分支(通过变更集编号或标签).再次,这成为另一个文件夹.

在管理本地工作空间时,"一切都是文件夹"的概念是好消息. 如果要在标记/分支/中继上创建任意复杂的视图,在TFS世界中该任务可以简化为映射本地路径< - >服务器路径的非常简单的问题.

当然,这并不意味着你应该这样做.磁盘空间比网络带宽或服务器CPU周期便宜很多.更重要的是:映射越复杂,就越有可能意外地将错误的文件提交到错误的位置.我通常的建议是:

  1. 为您主动处理的每个分支/标记创建一个工作区.
  2. 在每个工作空间中,只创建一个到分支根的递归映射.
    • 如果由于树枝的大小而无法做到这一点,请避免使用斗篷.它们不是一个好的解决方案,因为它们不会与其他人制作的文件夹添加/重命名保持同步.最好使用一级映射到分支根目录+对所需文件夹的其他递归映射.
    • 如果这是不可能的,因为你的分支中没有包含构建时依赖项,那么你就会感到羞耻:)尽可能将最少的其他映射#添加到公共库中.
  3. 确保每个分支内的相对路径相同.(如果它们发生变化,结构中的变化会与makefile的变化同步传播.)
  4. 为我称之为"维护"的任务创建一个额外的工作空间.

该策略提供:

  • 零资源开销.上下文切换时不需要重新加载.
  • 心理开销低.要开始处理另一个分支,只需从磁盘打开解决方案的另一个副本.或者在Source Control Explorer中更改Workspace下拉列表.
  • 搞砸的可能性很小.由于分支仅限于自己的工作区,因此单击Checkin All将永远不会提交另一个分支中待处理的更改...或者更糟糕的是,您不能意外地更改旨在违反"不稳定"的"发布"分支"版本.

我想要做的是在我的硬盘上有根"Project/Website"文件夹,并且能够让它指向(映射到)标签,分支或主干,这取决于我正在做什么,而不是通过修复Visual Studio项目引用来解决问题.

这也是可能的.如前所述,您只是在为磁带/ CPU交换磁盘空间.如果你的基础设施支持它没什么大不了的 我个人会发现它在并行开发方面限制太多,加上更多的搞砸事件 - 但是在SVN上提出的人可能会有不同的感受.

以下是步骤:

  1. 创建一个工作区.将其映射到您打算下一步要处理的分支/标记/主干.
  2. 遵循上述所有其他指导原则.
  3. 当需要更改分支/标记/主干时,重新打开"工作空间"对话框并将同一本地文件夹指向新的服务器路径.
  4. 得到最新的.
    • 从TFS 2008开始,只要您进行此类更改,客户端就会自动提示您运行Get.
    • 从TFS 2008 SP1开始,有一种更好的方法.单击提示上的"否",然后运行tf get/remap.这只会下载两个分支之间的差异.这可以节省大量带宽/ CPU,具体取决于文件夹大小以及它们的相关程度.(实际上可以在非常小,非常相关的文件夹上占用更多的服务器CPU,或者[当然]根本不相关;使用良好的判断.但是,应该总是采用严格的带宽.)

‡在TFS中,当您创建分支时,它对用户显示为全新的文件夹层次结构.换句话说:当您先验地查看存储库时,没有明确的方法可以将"真实"文件/文件夹与分支区分开来.坦白说,没有太大区别."分支"只是另一个项目,恰好有> = 1个与之关联的合并历史元数据.大量的TFS命令依赖于所述元数据,您当然可以直接查询它,但它不会显示在简单的tf目录中.同时,因为每个分支在路径空间中占据唯一的位置,这意味着唯一地指定分支版本规范并不复杂或不复杂. $/path;变更集就足够了,就像任何其他项一样.

CVS采取相反的方法.分支时,路径不会更改.你所做的就是沿着另一个维度分割版本.这使得简单的案例很容易可视化:只有一棵树.当然,你只是把复杂性转移到其他地方.当您想要唯一地指定项目的版本时,知道路径和修订版号是不够的; 你也需要知道分支.如果您在一个分支中重命名文件但不重命名另一个分支怎么办?在TFS,没有人会关心,直到合并分支机构为止; 在CVS中只是查看存储库引发了问题.我相信你可以想到其他的微妙之处 - 我不熟悉它以了解它如何处理每个边缘情况.

大多数SCC系统介于这两个极端之间.让我们称TFS 2005/2008为"左",而CVS则为"右".

Subversion基本上位于TFS的"左"极上方.虽然实现方式非常不同,但是现在最终实现了合并跟踪,用户的分支视图几乎完全相同.(有人可能会说,在v1.5之前,它甚至比TFS更远一些.分支只是具有低级优化的副本;用户无法查询关系元数据.SourceSafe属于同一类别,如果由于缺乏系统范围的版本号,甚至还没有更远.)来自SVN世界的用户一旦理解了客户端/服务器工作空间模型并重新调整其术语,就不会有困难.(SVN在其术语中有很多CVS包袱,例如单词"tag";公平性TFS继承了VSS的一些口头谣言,例如,尽管默认情况下是编辑合并提交,但普遍使用"签入/签出".)

Perforce是TFS右侧的一个档次.他们的基础模型是相同的.它们具有满足一些常见用户场景的分支规范的附加概念- 例如快速了解"哪些文件夹代表分支",用于指定不需要完整路径的分支版本规范的快捷方式 - 但它只是语法糖.

TFS 2010位于右侧的另外几个缺口.与Perforce一样,他们创建了一个"分支对象"存储库,它独立于(但映射回)存储库树.每个分支还知道用户定义的分支层次结构中的关系(例如,父,子,无基础).

我将ClearCase放在右边2/3的位置.从服务器的角度来看,复杂的分支场景基本上发生在版本空间中.然而,它们在顶部有一个非常强大的"视图"系统.结果,用户实际看到的结构可能被操纵以类似于路径空间或某些混合.类似的可定制性级别适用于其本地工作空间映射.

大多数其他"企业"SCM约为右侧的3/4.(例如AccuRev,MKS,StarTeam)用户通常可以通过各种强大的方式查看存储库+分支树,但不能像CC一样灵活地配置系统本身.这可能是一件好事:)

如前所述,CVS位于最右侧.同上它的祖先RCS和SCCS.

对Monotone,BitKeeper及其衍生产品等分布式系统进行分类超出了这个答案的范围:)


§TFS中的几个新操作可以在没有工作空间的情况下完成:

  • 创建分支(tf分支/签入 - 需要2008 SP1)
  • 销毁物品(需要2008年)

其他一些需要映射到工作区,但不要求您下载任何文件:

  • 删除项目
  • 锁定物品
  • 以旧方式创建分支(tf branch/noget - 自2005年早期beta版以来可用)

还有一些需要部分映射和/或部分下载:

  • 合并仅需要映射和下载目标路径.
  • 重命名需要映射两个路径并下载目标.
  • Undelete/newname的作用类似于重命名.

我更喜欢在他们自己的"维护"工作区中进行这些操作,与我的日常开发隔离开来.拥有自己的工作空间也意味着我可以一举映射存储库的大部分而不实际下载它们.(相反,在"开发"工作区中,最好的做法是运行Get w/o任何限制路径范围.)正如我已经提到过几次,现在保持本地< - >服务器映射的广泛和简单意味着相对路径保持不变,引用不会中断,文件不会意外地发送或者发送到错误的地方; 每个人都更开心.

因人而异.