关于svn:Subversion存储库中的“branch”,“tag”和“trunk”是什么意思?

What do “branch”, “tag” and “trunk” mean in Subversion repositories?

我在颠覆(我猜是一般知识库)的讨论中经常看到这些词。在过去的几年里,我一直在为我的项目使用SVN,但我从未掌握过这些目录的完整概念。

它们是什么意思?


嗯,我不太同意尼克·雷塔格和一家分店的做法。标签只是一个标记

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

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

  • 标记将是您希望保留的主干或分支上的时间点。保存的两个主要原因是,要么这是软件的主要版本,无论是alpha、beta、rc还是rtm,要么这是应用主干上的主要修订之前软件最稳定的点。

在开源项目中,项目干系人不接受的主要分支可以成为分叉的基础——例如,与其他源代码共享同一原点的完全独立的项目。

分支树和标记子树与主干树的区别如下:

Subversion允许SysAdmins创建钩子脚本,这些脚本在某些事件发生时触发执行;例如,向存储库提交更改。对于典型的Subversion存储库实现来说,在创建后将包含"/tag/"的任何路径视为写保护是非常常见的;最终结果是,标记一旦创建,就不可变(至少对于"普通"用户)。这是通过钩子脚本完成的,如果标记是被更改对象的父节点,钩子脚本通过阻止进一步的更改来强制实现不可变性。

Subversion还增加了与"分支合并跟踪"相关的功能,以便将提交给分支的更改合并回主干中,并支持增量"智能"合并。


首先,正如@andrewfinnell和@kenliu指出的,在SVN中,目录名本身并不意味着什么——"主干、分支和标记"只是大多数存储库使用的一种常见约定。并不是所有的项目都使用所有的目录(不使用"标记"是很常见的),事实上,没有什么能阻止您随意调用它们,尽管破坏约定通常会令人困惑。好的。

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

  • 主干:主要开发区。这是代码的下一个主要版本所在的地方,通常具有所有最新的特性。好的。

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

  • 标签:每次发布一个版本(最终版本、候选版本(RC)和betas)时,都要为它做一个标签。这将为您提供一个代码在该状态下的时间点副本,允许您返回并在过去版本中重现任何错误(如果需要),或者按照原来的方式重新发布过去的版本。SVN中的分支和标记是轻量级的——在服务器上,它不会生成文件的完整副本,只是一个标记,表示"这些文件是在这个版本中复制的",只占用几个字节。考虑到这一点,您不应该关心为任何已发布的代码创建标记。正如我前面所说,标记经常被省略,而在发布时,变更日志或其他文档会澄清修订号。好的。

例如,假设您启动了一个新项目。您开始在"trunk"中工作,最终将以版本1.0发布。好的。

  • Trunk/-开发版,即将成为1.0版
  • 分支/空

完成1.0.0之后,您将主干分支到一个新的"1.0"分支,并创建一个"1.0.0"标记。现在,我们将继续研究主干中最终是1.1的内容。好的。

  • Trunk/-开发版,即将成为1.1版
  • 分支/1.0-1.0.0版本
  • 标签/1.0.0-1.0.0版本

您会在代码中遇到一些错误,并在主干中修复它们,然后将这些修复合并到1.0分支中。您也可以做相反的事情,修复1.0分支中的bug,然后将它们合并回主干,但通常情况下,项目只坚持单向合并,以减少丢失某些内容的机会。有时错误只能在1.0中修复,因为它在1.1中已过时。这并不重要:您只想确保不使用1.0中修复的相同bug发布1.1。好的。

  • Trunk/-开发版,即将成为1.1版
  • 分支/1.0-即将发布的1.0.1版本
  • 标签/1.0.0-1.0.0版本

一旦你发现足够的bug(或者一个关键的bug),你就决定做一个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,但您希望首先进行测试。在这种情况下,您可能需要做一个"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版本
  • tags/1.1beta 1-1.1 beta1版本

一旦您发布了1.1 final,您就从"1.1"分支中做了一个"1.1"标记。好的。

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

分支的另一个用途是用于功能。这是您分支主干(或某个发布分支)并单独处理新特性的地方。功能完成后,将其重新合并并删除分支。好的。

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

这个想法是当你在做一些破坏性的事情(这会阻碍或干扰其他人的工作)、一些实验性的事情(甚至可能不会让它进入),或者可能只是需要很长时间的事情(而且你害怕当你准备从主干分支1.2时,它会阻碍1.2的释放),你可以这样做。它孤立地存在于分支中。通常,通过将更改一直合并到主干中,可以使其保持最新状态,这样在完成后更容易重新集成(合并回主干)。好的。

还要注意,我在这里使用的版本控制方案只是众多方案中的一个。有些团队会将bug修复/维护版本设置为1.1、1.2等,主要更改为1.x、2.x等。这里的用法相同,但您可以将分支命名为"1"或"1.x",而不是"1.0"或"1.0.x"。(除此之外,语义版本控制对于如何进行版本号是一个很好的指导)。好的。好啊。


除了尼克所说的之外,您还可以在流线型上找到更多信息:并行软件开发的分支模式

enter image description here

在这个图中,main是主干,rel1-maint是分支,1.0是标记。


一般来说(工具不可知论视图),分支是用于并行开发的机制。SCM可以有0到N个分支。Subversion具有0。

  • 主干是Subversion推荐的一个主要分支,但决不会强迫您创建它。你可以称之为"主要"或"发布",或者根本没有一个!

  • 分支表示开发工作。它不应以资源(如"vonc_branch")命名,而应以以下名称命名:

    • "我的项目开发"或"我的项目合并"
    • 发布周界"myprojectc1.0"或"myproject2.3"或"myproject6..2"补丁1"…
  • 标记是文件的快照,以便轻松返回该状态。问题是标签和分支在Subversion中是相同的。我绝对会推荐偏执的方法:


    you can use one of the access control scripts provided with Subversion to prevent anyone from doing anything but creating new copies in the tags area.

标签是最终的。它的内容永远不会改变。从未。曾经。你忘了发行说明上的一行了吗?创建新标记。过时或删除旧的。

现在,我读了很多关于"在这样这样这样的分支中归并这样的分支,然后在主干分支中归并"。这被称为合并工作流,这里没有强制要求。这并不是因为你有一个主干分支,你必须合并回任何东西。

按照惯例,主干分支可以表示您的开发的当前状态,但是对于简单的顺序项目来说,这是一个具有以下特性的项目:

  • 没有"提前"开发(用于准备下一个版本,意味着这些更改与当前的"主干"开发不兼容)
  • 无需大规模重构(用于测试新的技术选择)
  • 以前版本没有长期维护

因为有了这些场景中的一个(或全部),你就得到了四个"集群",四个"当前开发",而不是你在那些并行开发中所做的所有事情都必须合并回"集群"。


在SVN中,标记和分支非常相似。

标记=定义的时间切片,通常用于发布

branch=开发可以继续进行的一个定义的时间切片,通常用于主要版本,如1.0、1.5、2.0等,然后在释放时标记分支。这允许您在继续支持生产版本的同时,中断主干中的更改。

trunk=development工作空间,这是所有开发都应该发生的地方,然后更改从分支版本合并回来。


它们没有任何正式的意义。文件夹是一个文件夹到斯文。它们是组织项目的普遍接受的方法。

  • 主干是您保存development主线的地方。分支文件夹是您可以创建分支的地方,很难在短时间内解释。

  • 分支是项目的一个子集的副本,您独立于主干进行工作。也许这是为那些可能不去任何地方的实验准备的,也可能是为下一个版本准备的,当它变得稳定时,您稍后会将其合并回主干中。

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

但就像我说的,对SVN来说,文件夹就是一个文件夹。branchtrunk和tag只是一种约定。

我在大量使用"复制"这个词。实际上,SVN并没有在存储库中完整复制内容。


主干是包含最新源代码和特性的开发行。它应该包含最新的bug修复,以及添加到项目中的最新特性。

分支通常用来做一些远离主干(或其他开发线)的事情,否则会破坏构建。新特性通常构建在一个分支中,然后再合并回主干中。分支通常包含不必为其分支的开发行批准的代码。例如,程序员可以尝试对分支中的某个内容进行优化,并且只有当优化得到满意时,才将其合并回开发行。

标记是存储库在特定时间的快照。不应该在这些方面发展。它们通常用于获取发布给客户机的内容的副本,以便您可以轻松访问客户机正在使用的内容。

这里有一个链接,指向一个很好的存储库指南:

  • 震源控制方法

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


现在这就是软件开发的问题了,对任何东西都没有一致的认识,每个人似乎都有自己的方式,但那是因为这是一个相对年轻的学科。

这是我简单的方法,

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

在某个特定的时间点,当主干似乎已经准备好释放时,它就被标记并释放了。

分支-分支目录包含实验和正在进行的工作。分支机构的工作一直保持在那里,直到被批准合并到主干中。对我来说,这是所有工作都要完成的地方。

例如:我可以有一个迭代5分支用于产品的第五轮开发,也可以有一个原型9分支用于第九轮试验,等等。

标签-标签目录包含批准的分支和主干版本的快照。每当一个分支被批准合并到主干中,或者发布了主干的一个版本,就在标签下创建一个已批准分支或主干版本的快照。

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


当我查找Opencv2计算机视觉应用程序编程食谱的作者的网站时,我发现了这个关于SVN的很棒的教程,我想我应该分享一下。

他有一个关于如何使用SVN以及短语"trunk"、"tag"和"branch"的意思的教程。

直接从他的教程中引用:

The current version of your software project, on which your team is currently working is usually located under a directory called trunk. As the project evolves, the developer updates that version fix bugs, add new features) and submit his changes under that directory.

At any given point in time, you may want to freeze a version and capture a snapshot of the software as it is at this stage of the development. This generally corresponds to the official versions of your software, for example, the ones you will deliver to your clients. These snapshots are located under the tags directory of your project.

Finally, it is often useful to create, at some point, a new line of development for your software. This happens, for example, when you wish to test an alternative implementation in which you have to modify your software but you do not want to submit these changes to the main project until you decide if you adopt the new solution. The main team can then continue to work on the project while other developer work on the prototype. You would put these new lines of development of the project under a directory called branches.


每个人的定义都略有不同的原因之一是Subversion实现了对分支和标记的零支持。Subversion基本上说:我们查看了其他系统中功能齐全的分支和标签,但没有发现它们有用,所以我们没有实现任何东西。只需将副本复制到具有名称约定的新目录中即可。当然,每个人都可以有稍微不同的约定。理解真正的标签和仅仅是复制+命名约定之间的区别请参见维基百科条目Subversion标记和分支。


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

分支目录是用来存放分支的,不管它们是什么。

tags目录基本上用于标记一组特定的文件。这样做是为了像版本这样的事情,您希望"1.0"在这些版本中是这些文件,"1.1"在这些版本中是这些文件。通常在制作标签后不修改它们。有关标签的更多信息,请参阅第4章。分支和合并(在具有Subversion的版本控制中)。


Tag = a defined slice in time, usually used for releases

我认为这就是人们通常所说的"标签"的含义。但在颠覆中:

They don't really have any formal meaning. A folder is a folder to SVN.

我觉得很困惑:一个对分支或标签一无所知的修订控制系统。从实现的角度来看,我认为颠覆创建"副本"的方法非常聪明,但我必须知道这是我所说的一种泄漏的抽象。

或者可能我使用简历的时间太长了。


我认为有些混淆来自于标记的概念和SVN中的实现之间的差异。对SVN来说,标记是一个复制的分支。修改标记被认为是错误的,事实上,如果您试图用../tags/修改任何内容,类似tortoissesvn的工具都会警告您。在小路上。


我不太确定"tag"是什么,但branch是一个相当常见的源代码管理概念。

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

首先你要创建一个分支。这基本上是您创建分支时主干的副本。然后你将在这个部门里完成你所有的工作。在分支中所做的任何更改都不会影响主干,因此主干仍然可用,允许其他人继续在那里工作(例如进行错误修复或小的增强)。一旦您的特性完成,您将把分支集成回主干中。这将把所有的更改从分支转移到主干。

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

这是维基百科上关于分支的条目,因为它们可能比我解释得更好。:)


对于熟悉git的人来说,git中的master相当于SVN中的trunk。

branch和tag在git和svn中都有相同的术语。


主干:在敏捷的每一个冲刺完成之后,我们都会得到一个部分可交付的产品。这些释放物保存在后备箱中。

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

标签:每次我们发布一个部分可发货的测试版产品时,我们都会为它做一个标签。这给了我们当时可用的代码,允许我们在开发过程中的某个时候,如果需要,可以回到那个状态。