Subversion存储库中的“分支”,“标签”和“主干”是什么意思?


1193

在Subversion(我想是通用存储库)的讨论中,我经常看到这些词。在过去的几年中,我一直在项目中
使用SVN,但是我从来没有掌握过这些目录的完整概念。

他们的意思是什么?


29
这是我写的一篇很好的文章,解释了如何/何时使用主干,分支和标签。我以前没有使用过源代码控制,但是本文使像我这样的菜鸟很容易理解。Subversion的日常运作
Badmoon'Aug

Answers:


910

嗯,不确定我是否同意Nick re tag与分支相似。标签只是一个标记

  • 从项目开始到现在,干线将是开发的主体。

  • 分支将是从主干中某个点派生的代码副本,用于在保留主干中代码完整性的同时对代码进行重大更改。如果重大更改按计划进行,则通常会将它们合并回主干。

  • 标签将是您要保留的主干或分支上的时间点。保留的两个主要原因是:这是该软件的主要发行版(无论是alpha,beta,RC还是RTM),或者这是在应用主干上的主要修订之前该软件的最稳定点。

在开放源代码项目中,项目涉众不接受到主干中的主要分支可以成为分支的基础-例如,与其他源代码具有共同起源的完全独立的项目。

分支和标记子树通过以下方式与主干区分开来:

Subversion允许系统管理员创建挂钩脚本,当某些事件发生时,挂钩脚本将触发执行。例如,对存储库进行更改。典型的Subversion存储库实现通常将包含“ / tag /”的任何路径创建后都进行写保护。最终结果是,标签一旦创建便是不可变的(至少对于“普通”用户而言)。这是通过钩子脚本完成的,如果标记是已更改对象的父节点,则该钩子脚本通过阻止进一步的更改来增强不变性。

从版本1.5开始,Subversion还增加了与“分支合并跟踪”有关的功能,以便可以对提交给分支的更改进行合并,并支持增量的“智能”合并。


284
标签和分支的困惑在于,在svn中,除了目录名之外,它们之间确实没有区别。在svn中,您可以将更改提交给标签,实际上很难防止这种情况。大多数其他VCS将标签视为不变的快照(时间点)。
刘坚

4
Tags该目录也经常用于普通用户的里程碑测试和验证。这也是放置原型的好地方(只是一些想法浮现在脑海)。
杰夫·诺埃尔

6
@KenLiu有些钩子可以使标签不可变。也就是说,您可以创建和签出标签,但不能进行任何更改。当然,标记只是存储库的一部分,意味着可以使用完整的历史记录。如果有人更改了标签,则可以跟踪它以及原因。在许多VCS中,如果您修改标签,则可能无法知道。
David W.

3
也许应该提到稳定的分支:通常在那里所做的更改通常不会合并到主干中
狼”

4
我的理解是,在“完美的世界”中,主干中永远不会发生任何开发,主干应该始终是实时的确切代码或即将发布的实时代码。因此,这将使分支机构成为发展的主体。
MikeT

556

首先,就像@AndrewFinnell和@KenLiu指出的那样,在SVN中,目录名称本身没有任何意义-“主干,分支和标签”只是大多数存储库使用的通用约定。并非所有项目都使用所有目录(完全不使用“标签”是很普遍的做法),实际上,尽管违反约定通常会造成混乱,但没有什么可以阻止您调用它们。

我将描述分支和标签的最常见使用场景,并给出如何使用它们的示例场景。

  • 主干:主要开发区域。这是您的代码的下一个主要版本所在的位置,并且通常具有所有最新功能。

  • 分支:每次发布主要版本时,都会创建一个分支。这样,您就可以进行错误修复并发布新版本,而不必发布最新的功能(可能尚未完成或未经测试)。

  • 标签:每次发布版本(最终版本,候选发布版(RC)和Beta版)时,您都会为其标记。这为您提供了当时状态下的代码的时间点副本,允许您在必要的情况下返回并重现任何错误,或者在以前的版本中完全重新发布。SVN中的分支和标记是轻量级的-在服务器上,它不制作文件的完整副本,只是一个标记说“这些文件是在此版本中复制的”,仅占用几个字节。考虑到这一点,您永远不必担心为任何已发布的代码创建标签。正如我之前所说,标记通常被省略,取而代之的是,发布版本时,变更日志或其他文档阐明了修订版本号。


例如,假设您开始一个新项目。您开始在“ trunk”中工作,最终将以1.0版发布。

  • trunk /-开发版本,即将发布1.0
  • 分支机构/-空

1.0.0完成后,将中继分支到新的“ 1.0”分支,并创建“ 1.0.0”标签。现在,关于最终将是1.1的工作将继续进行。

  • trunk /-开发版本,即将发布1.1
  • branchs / 1.0-1.0.0发行版本
  • 标签/1.0.0-1.0.0发行版本

您会在代码中遇到一些错误,并在主干中对其进行修复,然后将这些修复程序合并到1.0分支中。您也可以执行相反的操作,并修复1.0分支中的错误,然后将其合并回主干,但是通常项目坚持单向合并,以减少丢失某些内容的机会。有时,错误只能在1.0中修复,因为它在1.1中已过时。其实并不重要:您只想确保您不会发布与1.0中已修复的相同错误的1.1。

  • trunk /-开发版本,即将发布1.1
  • 分支机构/1.0-即将发布的1.0.1版本
  • 标签/1.0.0-1.0.0发行版本

一旦发现足够的错误(或可能是一个严重的错误),便决定执行1.0.1版本。因此,您可以从1.0分支中创建一个标记“ 1.0.1”,然后释放代码。此时,主干将包含1.1,而“ 1.0”分支包含1.0.1代码。下次发布对1.0的更新时,它将是1.0.2。

  • trunk /-开发版本,即将发布1.1
  • 分支机构/1.0-即将发布的1.0.2
  • 标签/1.0.0-1.0.0发行版本
  • 标签/1.0.1-1.0.1发行版本

最终,您几乎已经准备好发布1.1,但是您想先进行Beta测试。在这种情况下,您可能会执行“ 1.1”分支和“ 1.1beta1”标记。现在,将在主干中继续进行关于1.2(或2.0)的工作,而在“ 1.1”分支中继续进行关于1.1的工作。

  • trunk /-开发版本,即将发布1.2
  • 分支机构/1.0-即将发布的1.0.2
  • 分支机构/1.1-即将发布的1.1.0版本
  • 标签/1.0.0-1.0.0发行版本
  • 标签/1.0.1-1.0.1发行版本
  • 标签/1.1beta1-1.1 beta 1发行版本

一旦发布了1.1最终版,就可以从“ 1.1”分支中执行“ 1.1”标签。

如果愿意,还可以继续维护1.0,在所有三个分支(1.0、1.1和trunk)之间移植bug修复程序。重要的一点是,对于要维护的软件的每个主要版本,您都有一个分支,其中包含该版本的最新代码。


分支的另一种用途是用于功能。在这里,您可以分支干线(或其中一个发布分支),并单独开发新功能。功能完成后,将其合并回去并删除分支。

  • trunk /-开发版本,即将发布1.2
  • 分支机构/1.1-即将发布的1.1.0版本
  • 分支/ ui重写-实验功能分支

这样的想法是,当您正在从事破坏性的工作(可能阻碍或干扰他人的工作),正在尝试的工作(甚至可能无法完成工作)或可能需要很长时间时(而且,当您准备从主干分支到1.2时,如果担心它支撑着1.2版本),您可以在分支中单独进行操作。通常,您可以通过始终将更改合并到主干中来使其保持最新状态,从而在完成后更容易重新集成(合并回主干)。


还要注意,我在这里使用的版本控制方案只是众多方案之一。有些团队会进行1.1 / 1.2等错误修复/维护,而对1.x,2.x等进行主要更改。这里的用法相同,但是您可以将分支命名为“ 1”或“ 1” .x”,而不是“ 1.0”或“ 1.0.x”。(此外,语义版本控制是有关如何执行版本号的良好指南)。


6
@baruch-完全错误。标签是轻量级的,并且(就Subversion本身而言)与分支相同。
2014年

7
喜欢用例的细节。谢谢@gregmac。
Jeromy French

2
我可以得到有关标签/分支轻巧的地方的报价吗?似乎不是这样
。-卡丹·李

3
这应该是公认的答案,这样的答案要好得多^^
Nam G VU

4
@Cardin我现在没有参考,但是要注意的是,服务器上的标签是轻量级的,但客户端不是轻量级的。如果签出所有标签,将获得那么多完整的副本。但是,如果您查看服务器上的存储库大小,则每个标签只会增加几个字节。通常,这就是为什么您不应该签出根目录的原因。
gregmac '16

97

除了Nick所说的之外,您还可以在Streamed Lines:并行软件开发的分支模式中找到更多信息。

在此处输入图片说明

在此图main中,主干rel1-maint是分支,1.0是标签。


1
他可能是@Wolf-无论使用哪种工具,该图都非常通用。所有SCM都使用不同的词,但是概念相同,trunk和Main之间没有区别。或树干和主人。该图显示了我当前的公司如何使用SVN。
gbjbaanb 2015年

@gbjbaanb感谢您的分享。...而且问题似乎无法解决标签。纯粹是出于巧合(在您当前的公司中也是如此),没有合并从主分支转到维护分支吗?
狼”

@Wolf没有巧合-仅从主干分支,开始工作,再合并回主干。然后将中继线分支到标签分支。我们正在考虑另一个称为“集成”的“主干”,它已经完成了合并到分支的测试,这不构成发行版,主干仍用于我们决定放入下一个发行版的那些分支。从主干合并到分支的唯一时间是更新一个运行时间较长的分支,但是更好(更容易)的方法是简单地在主干之外创建新分支,并在需要时将旧分支的更改合并到分支中。
gbjbaanb 2015年

75

通常,(与工具无关的视图)分支是用于并行开发的机制。一个SCM可以有0到n个分支。Subversion有0。

  • TrunkSubversion 推荐的主要分支,但绝不强迫您创建它。您可以将其称为“主要”或“发布”,也可以根本没有!

  • 分支代表开发工作。永远不要以资源(例如“ vonc_branch”)为名,而要以:

    • 目的“ myProject_dev”或“ myProject_Merge”
    • 发布范围'myProjetc1.0_dev'或myProject2.3_Merge'或'myProject6..2_Patch1'...
  • 标记是文件的快照,以便轻松返回到该状态。 问题是Subversion中的tag和branch相同。我绝对会推荐偏执的方法:

    您可以使用Subversion随附的一种访问控制脚本来阻止任何人执行任何操作,除了在标记区域中创建新副本。

标签是最终的。它的内容永远不会改变。决不。曾经 您在发行说明中忘了一行吗?创建一个新标签。过时或删除旧的。

现在,我读了很多有关“将这样的分支合并到这样的分支中,然后最终合并到主干分支中”的文章。这称为合并工作流,这里没有强制要求。并不是因为您有主干分支,所以您必须合并任何内容。

按照惯例,主干分支可以代表开发的当前状态,但这是针对简单的顺序项目的,即具有以下内容的项目:

  • 没有“预先”开发(用于准备下一个下一个版本,暗示这些更改与当前的“ trunk”开发不兼容)
  • 无需大量重构(用于测试新的技术选择)
  • 无需长期维护以前的版本

因为使用这些场景中的一个(或全部),您将获得四个“主干”,四个“当前开发”,而并非您在这些并行开发中所做的所有工作都必须合并回“主干”。


38

在SVN中,标记和分支确实很相似。

Tag =定义的时间片,通常用于发布

分支 =也是可以继续进行开发的时间片,通常用于主要版本(例如1.0、1.5、2.0等),然后在发布时标记分支。这使您可以继续支持生产版本,同时继续进行主干中的重大更改。

Trunk =开发工作空间,应在此处进行所有开发,然后将更改从分支版本中合并回去。


30

它们实际上没有任何正式含义。文件夹是SVN的文件夹。它们是组织项目的普遍接受的方式。

  • 主干是您保持开发主线的地方。分支文件夹是您可以在其中创建分支的位置,在简短的帖子中很难解释。

  • 分支是您与干线分开工作的项目子集的副本。也许是针对可能无法进行的实验,或者是针对下一个版本,您将在稳定后将其合并到主干中。

  • 标签文件夹用于创建存储库的标签副本,通常是在发布检查点。

但是就像我说的那样,对于SVN,文件夹就是文件夹。branchtrunk和标签只是一个惯例。

我在自由地使用“复制”一词。SVN实际上不会在存储库中制作事物的完整副本。


13

干线是发展线保持最新的源代码和功能。它应该具有最新的错误修复以及添加到项目中的最新功能。

分支通常用于从主干(或其他发展路线),否则将做一些东西打破构建。新功能通常建在分支中,然后合并回主干。分支通常包含未必为其分支开发线批准的代码。例如,程序员可以对分支中的某些内容进行优化,并且只有在优化令人满意的情况下,才可以合并到开发线中。

标签是在特定时间存储库的快照。在这些方面不应该发展。它们最常用于复制发布给客户端的内容,以便您可以轻松访问客户端使用的内容。

这是一个非常好的存储库指南的链接:

维基百科中的文章也值得一读。


12

现在是关于软件开发的事情,对于任何事情都没有统一的知识,每个人似乎都有自己的方式,但这是因为无论如何这都是一门相对年轻的学科。

这是我简单的方式,

trunk-主干目录包含最新的,批准的和合并的工作体。与许多人承认的相反,我的后备箱仅用于清洁,整洁,经过批准的工作,而不是用于开发区域,而是用于发布区域。

在某个特定的时间点,当中继线似乎都准备好释放时,便会对其进行标记和释放。

分支 -分支目录包含实验和正在进行的工作。分支机构下的工作会一直待在那里,直到批准合并到主干中为止。对我来说,这是完成所有工作的区域。

例如:对于产品的第五轮开发,我可以有一个迭代5分支,对于第九轮实验,可以有一个原型9分支,依此类推。

标签 -标签目录包含批准的分支和主干版本的快照。每当批准分支合并到主干中或发布主干时,都会在标签下创建批准的分支或主干发布的快照。

我想有了标签,我可以很容易地在时间上来回跳动来指出兴趣。


10

当我查阅《OpenCV 2计算机视觉应用程序编程手册》作者的网站时,发现了关于SVN的出色教程,我认为应该分享。

他提供了有关如何使用SVN以及“ trunk”,“ tag”和“ branch”的含义的教程。

直接从他的教程中引用:

您的团队当前正在使用的软件项目的当前版本通常位于名为trunk的目录下。随着项目的发展,开发人员将更新该版本的修复错误,添加新功能)并在该目录下提交其更改。

在任何给定的时间点,您可能都希望冻结版本并捕获软件快照,就像在开发的此阶段一样。这通常对应于您的软件的正式版本,例如,您将交付给客户的版本。这些快照位于项目的标签目录下。

最后,在某个时候为您的软件创建新的开发线通常很有用。例如,当您希望测试一个替代实现时,您必须修改软件,但又不想将这些更改提交给主项目,直到您决定是否采用新解决方案时,才会发生这种情况。然后,主要团队可以继续从事该项目,而其他开发人员则从事原型工作。您可以将项目的这些新开发线放在一个名为branchs的目录下。


9

主干目录是您可能最熟悉的目录,因为它用于保存最新更改。您的主要代码库应该在主干中。

分支目录用于保存分支(无论分支如何)。

标签目录主要用于标记一组文件。您可以针对发行版(例如发行版)执行此操作,在该发行版中,您希望“ 1.0”成为这些修订版的这些文件,而希望“ 1.1”成为这些修订版的这些文件。标记一旦制成,通常就不会对其进行修改。有关标签的更多信息,请参见第4章。分支和合并(在Subversion的Version Control中)。


9

每个人的定义稍有不同的原因之一是因为Subversion 对分支和标签实现了支持。Subversion基本上说:我们查看了其他系统中功能齐全的分支和标记,但发现它们没有用,因此我们没有实现任何东西。只是做一个拷贝与一个名称的新目录约定代替。那么,当然每个人都可以自由选择略有不同的约定。要了解真实标签和纯拷贝+命名约定之间的区别,请参阅Wikipedia条目Subversion标签和分支


8

Tag =定义的时间片,通常用于发布

我认为这就是“标签”的典型含义。但是在Subversion中:

它们实际上没有任何正式含义。文件夹是SVN的文件夹。

我觉得这很令人困惑:对分支或标签一无所知的版本控制系统。从实现的角度来看,我认为创建“副本”的Subversion方法非常聪明,但是我必须知道这就是所谓的泄漏抽象

或者也许我刚刚使用CVS太久了。


另一种观点是相反的说法是正确的,即将标签的概念强加在Subversion的对象模型上将是相反方向上的泄漏抽象。就像我猜到的那样,颠覆是对CVS的一种反应,是“正确执行CVS”的尝试。我找不到参考资料,但是最初的Subversion设计师说他们有意100%地放弃了标签的概念,即分支和标签之间的区别纯粹是一个政策问题。如果团队希望在Subversion的对象模型之上施加策略和约定,那就去吧。这就是我们今天所拥有的。
达里尔

6

我认为某些混淆来自标记概念和SVN中实现之间的差异。对于SVN,标签是一个分支,即一个副本。修改标签被认为是错误的,实际上,如果您尝试在路径中使用../tags/ ..进行任何修改,则诸如TortoiseSVN之类的工具会警告您。


5

我不太确定“标签”是什么,但是分支是一个相当普遍的源代码管理概念。

基本上,分支是一种在不影响主干的情况下进行代码更改的方法。假设您要添加一个相当复杂的新功能。您希望能够在进行更改时签入更改,但不希望更改影响中继,直到您完成该功能。

首先,您将创建一个分支。基本上,这是创建分支时的主干副本。然后,您将在分支机构中完成所有工作。在分支中所做的任何更改都不会影响中继,因此中继仍然可以使用,从而允许其他人在中继上继续工作(例如进行错误修复或小的增强)。一旦完成功能,就可以将分支集成回主干。这会将所有更改从分支移动到主干。

人们在分支机构中使用多种模式。如果您的产品同时支持多个主要版本,则通常每个版本都是一个分支。在我工作的地方,我们有一个质量检查部门和一个生产部门。在将代码发布到质量检查之前,我们将更改集成到质量检查分支,然后从那里进行部署。在发布到生产环境时,我们从QA分支集成到Production分支,因此我们知道生产环境中运行的代码与QA测试的代码相同。

这是分支上的Wikipedia条目,因为它们可能比我能更好地解释事情。:)


4

躯干:在完成每个敏捷的冲刺之后,我们推出了部分可交付的产品。这些版本保存在主干中。

分支:每个正在进行的sprint的所有并行开发代码都保存在分支中。

标签:每次发布部分可交付产品的Beta版本时,我们都会为其做一个标签。这为我们提供了当时可用的代码,并允许我们在开发过程中的某个时候返回到该状态。


这是您的特定工作流程,通常不适用。
杰森S

4

对于熟悉GIT的人,GIT的主级相当于SVN的主干。

在GIT和SVN中,分支和标记具有相同的术语。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.