在SCM中正确使用标签

时间:2009-04-08 13:19:10

标签: version-control release-management

我的同事和我正在讨论发布/ SCM系统中标签的价值和用法。我们希望StackOverflow社区能够帮助我们解决问题。

一方声称标签是发布管理的一个有价值的补充。它们的一个使用示例:我们做了一个Maven版本,它发布了一个新的Tag(称之为1.0),这是用于此版本的代码快照。此标记应为READONLY分支。当需要修复bug时,我们可以将Tag的副本复制到一个新的分支中(称之为1.1)。错误修复去那里。这些修复程序可能会合并回Trunk,以便主dev分支获取错误修复程序。最后,1.1发布并自动创建Tag 1.1。这个循环继续。 Tag的主要好处是,如果您因任何原因需要重新发布版本1.0,您可以放心发布Tag 1.0,并确信它从未被任何人更改过。此外,说“发布标签1.0”比说“发布1.0版本的修订版1是没有修复的原始1.0”更清晰。

另一方声称标签没有提供任何有价值的好处,特别是在像Subversion这样的全局修订系统中,它就像CVS中的标签一样。另外,Subversion仅在提交标签时发出警告;它实际上并没有阻止它。他们的方法是在Trunk中开发,一旦发布,你就会创建一个名为1.0的分支。您将继续在Trunk中修复错误,如果您需要将这些错误修复重新发布到生产中,您可以将它们合并到1.0 Branch并重新发布1.0。在某些时候,也许在Trunk中的主要修复或功能之后,您将发布并创建Branch 1.1。循环继续。如果您需要发布原始1.0版本,则必须查看Branch 1.0版本1。

显然这两种方法都有效。我想听听社区关于哪种方法更受欢迎以及原因的想法。

编辑:我有点担心“最佳”方式取决于底层的SCM系统。要么在Subversion上找到答案,要么尽可能保持SCM不可知。

8 个答案:

答案 0 :(得分:4)

在我看来,标签很有用。在项目的生命中某些时候,您会遇到一个错误或更改,并且您想知道它是否存在于先前版本中。有理由将一个版本的代码与另一个版本的代码进行比较,以衡量性能和实际代码开发的效率。

当然,你有可能搞砸它,但它总是可以撤消。没有理由不这样做,并且有几个原因可以在将来使用它。对我而言,这是一个明智的选择。

我同意您也应该使用分支机构并在那里进行开发,但是无论何时实际发布某些内容,都可以使用分支机构。

答案 1 :(得分:4)

从SCM不可知论的角度来看,标签与修订版非常不同。

两者都可以用同样的方式实现,两者都代表“时间线”,但他们的目标是不同的:

  • 标记表示不可变状态,其中所有文件都由唯一ID引用。它是一个名称representing many things,但主要是一个稳定的状态,...)
  • 修订表示提交事务(not all SCM have those,尤其是具有“逐个文件方法”的旧事务。所有提交都不代表“稳定”状态(如“编译”或“执行”成功)。它们只是全球历史的新元素。

SVN的问题在于版本,标签和分支都是相同的 但我仍然更喜欢将标签用作"read-only" branch的选项。

答案 2 :(得分:1)

是的,你想使用标签。

将标记视为特定修订的标签或名称。根据我的经验,标记项目中的重要里程碑非常有用,无论是用于生产发布还是用于临时QA版本。您经常需要及时返回并查看特定版本的源代码。

如果你在发布时分支,你总是可以找出发布到生产的版本,但与仅查看标签相比,这是一种痛苦。如果您不使用发布分支,那么很容易忘记用于创建特定构建的修订版。

svn的问题在于它模糊了标签和分支之间的区别。任何人都可以始终提交标记,因此不保证是固定/不可变的。在像PVCS这样的其他VCS中,“标签”是不可更改的。您可以采用团队约定来阻止对标记的提交,甚至可以使用提交挂钩来阻止对标记的提交。

答案 3 :(得分:1)

我们在创建新基线时使用标签(标签)。我们每周做一次,但有些团队每天都会做几次。

关键点(对我们而言)始终确保新基线是稳定的:因此它不仅仅是一个构建,是一个通过整个测试套件的构建,几个小时的自动化测试以及可能还有手动探索的构建。

然后在下一次迭代期间将基线用作所有任务的起点:每个新任务都是从基线开始的新分支,已知该分支是稳定的,因此任务中的任何内容都应该很容易在内部跟踪任务本身。

通常我们只将标签(标签)放在主分支(或主干或主服务器上,具体取决于您的SCM风格),这是所有其他分支的集成点。

当我们发布官方产品时,我们会为它创建一个“发布分支”,因此只有在新开发保持“主要”时它才会收到修复。然后,这些“维护分支”(希望一次只有一两个)也可以被标记。

答案 4 :(得分:0)

我喜欢将标签视为“仅仅是修订的奇特名称”。我总是这样想着他们,而IIRC在他们身上就是这样。然而,在subversion中,正如你所说,它们确实是(便宜)trunk / * to tags / fancy-name /

的副本

老实说,我将两种策略结合起来以获得最佳结果:标签和分支在发布时。您的标记名为1.0.0,分支1.0-MAINT。错误修正进入分支,错误修复版本再次是标记(1.0.1可能是由某个标记打算在某一点别名为1.0-MAINT。)

不要忘记,颠覆中的标签和分支实际上是同一件事:便宜的副本。它们之间的唯一区别是你/你的团队对它们的语义,所以它几乎归结为让人们就一种特殊方法达成一致并坚持下去(可能在服务器上强制执行,例如禁止在标签中提交/除了发布协调员等。)

我用第二种方法看到的问题是:如果重新发布1.0,你将如何轻松区分现场软件?这意味着你可能有一个1.0而另一个1.0实际上指的是不同的代码库...。

答案 5 :(得分:0)

项目源代码(和可执行文件)的不可变快照对于进行任何类型的测试都是非常宝贵的,无论是结构化测试还是现场使用。对于结构化测试,您将创建可能在未来数月或数年引用的数据。任何时候你重新访问这些数据,Murphy定律说你需要知道它来自哪个代码,除非你引用了源代码的特定快照的麻烦,否则无法自信地告诉你源代码是什么源代码。测试数据。

我无法告诉你有多少人来找我并说“这个微控制器代码无法正常工作,你能帮忙吗?”我问他们,“你用的是哪个版本?”他们说“我不确定”,因为他们没有做好发布管理(至少在设备上贴上标签,最好将版本信息放在EEPROM中,可以实时查询)。 >:(

答案 6 :(得分:0)

在SVN中,使用标记和跟踪修订版之间的技术差异为零。我发现自己最大限度地减少了标签的使用,这取决于SVN的实现方式只是一个廉价的副本,并使你的“结构空间”变得混乱。

真正的区别在于与大型开发团队沟通特定基线时。修订跟踪带来了额外的抽象层,可能成为错误的来源。而且我们都知道,当你与50多个开发人员打交道时,任何错误来源都会成为一个混乱和浪费时间的领域。详细标记可以消除这种混淆,并消除对基线目的的疑虑。

答案 7 :(得分:0)

我将这两种方法结合起来。无论何时发布,都要标记它。标签永远不会改变,因此“1.0.0”标签的存在表明您不应该尝试以1.0.0的形式发布任何其他内容。

与此同时,当需要做1.0.0时,我会将它放到1.0分支上。所以流程是:分支主干到1.0,将这个新1.0标记为1.0.0,并进行部署。然后可以在1.0分支上完成错误修复(以避免与现在可能已经在主干上的任何1.1目标开发混淆)并合并到主干中。固定1.0的每个版本都从1.0分支标记为1.0.x.这基本上是我们在使用Perforce时使用的方法,这与Subversion非常相似。 (阅读回复,我认为这几乎与文森特的推荐相同)

关于标签冗余的评论,因为你有修订号 - 这在很大程度上是正确的,除了标签还指定了一个范围:即标签中的哪些文件被标签覆盖。您可以合理地要求某人查看/svn/proj1/tag/1.0.0,他们会立即查看连贯的工作区。如果你要求他们查看修订版X,他们必须首先查看修订版X,看它是否正在改变(例如)/ svn / proj1 / trunk / Makefile,因此推断出/ svn / proj1 / trunk / @ X是什么他们应该看看。如果修订版X触及proj1和proj2中的文件会发生什么?这当然是邪恶的,但严格来说你应该说/ svn / proj1 / trunk / @X。存储的修订号列表在哪里?我们怎么知道1.0.0是修订版X?应该恕我直言,可以从存储库中确定。

在像Git这样的系统中,标签和分支仍然基本相同(只是对对象数据库的引用),但约定是标签引用不改变,而分支refs做(并且最好对它们如何变化有特定的约束)。 Perforce还有“标签”,它们是一组独立于变更列表对一组文件修订进行分组的方法;这实际上是一个标签,但更令人困惑:从历史上看,我们使用了变更列表编号(相当于Subversion版本号),并使用它们应该用于分支的名称来识别版本。两者几乎完全相同,所以我猜TMTOWTDI。