ChatGPT解决这个技术问题 Extra ChatGPT

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

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

他们的意思是什么?

这是我遇到的一篇很好的文章,解释了如何/何时使用主干、分支和标签。我以前没有使用过源代码管理,但是这篇文章让像我这样的菜鸟很容易理解。 Day-to-day with Subversion

J
JoGusto

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

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

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

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

在开源项目中,项目利益相关者不接受主干的主要分支可以成为分支的基础——例如,与其他源代码共享同一来源的完全独立的项目。

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

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

从 1.5 版开始,Subversion 还添加了与“分支合并跟踪”相关的功能,以便提交到分支的更改可以合并回主干,支持增量、“智能”合并。


与标签和分支的混淆在于,在 svn 中,除了目录名称之外,它们之间确实没有区别。在 svn 中,您可以提交对标签的更改,实际上很难防止这种情况发生。大多数其他 VCS 将标签视为不可变的快照(时间点)。
Tags 目录也经常被普通用户用于里程碑测试和验证。这也是放置原型的好地方(只是我头脑中的一些想法)。
@KenLiu 有一些钩子可以使标签不可变。也就是说,您可以创建和签出标签,但不能进行任何更改。当然,标签只是存储库的一部分意味着完整的历史记录可用。如果有人更改了标签,您可以跟踪它以及原因。在很多 VCS 中,如果你修改了一个标签,可能没有任何办法知道。
也许应该提到稳定的分支:在那里所做的更改通常不会合并回主干。
我的理解是,在“完美世界”中,主干中不应该发生任何开发,主干应该始终是实时的确切代码或即将发布的代码。因此,这将使分支机构成为发展的主体。
g
gregmac

首先,正如@AndrewFinnell 和@KenLiu 指出的那样,在SVN 中,目录名称本身没有任何意义——“主干、分支和标签”只是大多数存储库使用的通用约定。并非所有项目都使用所有目录(完全不使用“标签”是相当普遍的),事实上,没有什么能阻止你随意调用它们,尽管打破惯例常常令人困惑。

我将描述可能最常见的分支和标签使用场景,并举例说明如何使用它们。

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

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

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

例如,假设您开始一个新项目。您开始在“主干”中工作,最终将作为 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 分支中的错误,然后将它们合并回主干,但通常项目坚持单向合并只是为了减少丢失某些东西的机会。有时一个错误只能在 1.0 中修复,因为它在 1.1 中已过时。这并不重要:您只需要确保您发布的 1.1 版本中不会出现 1.0 版本中已修复的相同错误。

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 发布版本

tags/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 发布版本

tags/1.0.1 - 1.0.1 发布版本

tags/1.1beta1 - 1.1 beta 1 发布版本

一旦你发布了 1.1 final,你从“1.1”分支做一个“1.1”标签。

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

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

trunk/ - 开发版本,即将是 1.2

分支/1.1 - 即将发布的 1.1.0 版本

分支/ui-rewrite - 实验功能分支

这个想法是当你在做一些破坏性的事情(这会阻碍或干扰其他人做他们的工作),一些实验性的事情(甚至可能无法进入),或者可能只是一些需要很长时间的事情(当您准备从主干分支 1.2 时,您担心如果它阻止 1.2 版本),您可以在分支中单独执行此操作。通常,您通过始终将更改合并到主干来使其与主干保持同步,这使得完成后重新集成(合并回主干)变得更容易。

另请注意,我在这里使用的版本控制方案只是其中之一。一些团队会将错误修复/维护版本作为 1.1、1.2 等进行,而将主要更改作为 1.x、2.x 等。这里的用法是相同的,但您可以将分支命名为“1”或“1” .x”而不是“1.0”或“1.0.x”。 (除此之外,semantic versioning 是关于如何制作版本号的一个很好的指南)。


@baruch - 这是完全错误的。标签是轻量级的并且(就 Subversion 本身而言)与分支相同。
喜欢用例细节。谢谢@gregmac。
我可以得到关于标签/分支是轻量级的报价吗?好像不是这样的。。
这应该是公认的答案,这要好得多^^
@Cardin我现在没有参考,但重要的是要注意标签在服务器上是轻量级的,但不是客户端。如果你检查所有标签,你会得到那么多完整的副本。但是,如果您查看服务器上的存储库大小,每个标签只会增加几个字节。这就是为什么你不应该检出根目录的原因,一般来说。
B
Ben

除了尼克所说的,您可以在 Streamed Lines: Branching Patterns for Parallel Software Development 找到更多信息

https://i.stack.imgur.com/oBsKl.gif

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


@Wolf 他可能是-无论工具如何,该图都非常通用。所有的单片机使用不同的词但相同的概念,主干和主干没有区别;或主干和主控。该图显示了我当前的公司如何使用 SVN。
@gbjbaanb 感谢分享。 ...并且标签似乎没有被问题解决。没有合并从主要分支到维护分支,这纯属巧合(也在您当前的公司中)?
@Wolf并非巧合-仅从主干分支,工作,合并回主干。然后将主干分支到标签分支。我们正在考虑另一个名为 Integration 的“主干”,它已完成合并到它的分支以进行不构成发布的测试,主干仍用于我们决定放入下一个版本的那些分支。从主干合并到分支的唯一一次是更新一个长期运行的分支,但如果需要,只需从主干创建一个新分支并将旧分支的更改合并到它会更好(也更容易)。
6
6 revs, 5 users 77%

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

Trunk 是 Subversion 推荐的主分支,但您绝不会被迫创建它。您可以将其称为“主要”或“发布”,或者根本没有!

分支代表开发工作。它永远不应该以资源命名(如“vonc_branch”),而是在:目的“myProject_dev”或“myProject_Merge”发布边界“myProjetc1.0_dev”或myProject2.3_Merge或“myProject6..2_Patch1”......

目的“myProject_dev”或“myProject_Merge”

发布周界“myProjetc1.0_dev”或 myProject2.3_Merge 或“myProject6..2_Patch1”...

标记是文件的快照,以便轻松返回该状态。问题是标签和分支在 Subversion 中是相同的。我肯定会推荐偏执的方法:您可以使用 Subversion 提供的访问控制脚本之一来防止任何人做任何事情,除了在标签区域创建新副本。

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

现在,我读了很多关于“在某某分支中合并某某,然后最终在主干分支中”的内容。这称为合并工作流程,这里没有任何强制性。这不是因为你有一个主干分支,你必须合并任何东西。

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

没有“提前”开发(用于准备下一个下一个版本,意味着这些更改与当前的“主干”开发不兼容)

没有大规模重构(用于测试新的技术选择)

不长期维护以前的版本

因为在这些场景中的一个(或所有)情况下,您会得到四个“主干”,四个“当前开发”,而并非您在这些并行开发中所做的所有事情都必须合并回“主干”中。


N
Nick Berardi

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

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

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

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


P
Peter Mortensen

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

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

分支是您的项目子集的副本,您与主干分开工作。也许它是用于可能不会去任何地方的实验,或者它可能是用于下一个版本,当它变得稳定时,您将稍后将其合并回主干。

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

但就像我说的,对于 SVN,文件夹就是文件夹。 branchtrunk 和标记只是一个约定。

我在自由地使用“复制”这个词。 SVN 实际上并没有在存储库中制作完整的副本。


m
mbillard

主干是拥有最新源代码和功能的开发线。它应该包含最新的错误修复以及添加到项目中的最新功能。

分支通常用于在主干(或其他开发线)之外做一些事情,否则会破坏构建。新功能通常构建在分支中,然后合并回主干。分支通常包含不一定被批准用于其分支的开发线的代码。例如,程序员可以尝试对分支中的某些内容进行优化,并且只有在优化令人满意时才合并回开发线。

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

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

源代码控制 HOWTO

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


B
BakerTheHacker

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

这是我简单的方法,

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

在某个给定时间点,当主干似乎已准备好释放时,它会被标记并释放。

分支 - 分支目录包含实验和正在进行的工作。分支下的工作会一直留在那里,直到被批准并入主干。对我来说,这是完成所有工作的地方。

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

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

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


C
Community

当我查找 OpenCV 2 Computer Vision Application Programming Cookbook 的 author 的网站时,我发现了这个关于 SVN 的精彩教程,我认为我应该分享。

他有一个关于如何使用 SVN 以及短语“trunk”、“tag”和“branch”含义的教程。

直接引用他的教程:

您的团队当前正在使用的软件项目的当前版本通常位于名为 trunk 的目录下。随着项目的发展,开发人员更新该版本修复错误,添加新功能)并在该目录下提交他的更改。在任何给定的时间点,您可能想要冻结版本并捕获软件在开发的这个阶段的快照。这通常对应于您的软件的官方版本,例如,您将交付给客户的版本。这些快照位于项目的 tags 目录下。最后,在某些时候为您的软件创建新的开发线通常很有用。例如,当您希望测试一个替代实现时,您必须修改您的软件,但您不想将这些更改提交到主项目,直到您决定是否采用新解决方案时,就会发生这种情况。然后,主要团队可以继续从事项目工作,而其他开发人员则从事原型工作。您可以将项目的这些新开发线放在一个名为分支的目录下。


P
Peter Mortensen

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

分支目录用于保存您的分支,无论它们是什么。

tags 目录基本上是用于标记一组文件。您为发布之类的事情执行此操作,您希望“1.0”成为这些修订版中的这些文件,而“1.1”成为这些修订版中的这些文件。制作标签后,您通常不会对其进行修改。有关标签的详细信息,请参阅 Chapter 4. Branching and Merging(在 Version Control with Subversion 中)。


P
Peter Mortensen

每个人的定义略有不同的原因之一是因为 Subversion 实现了对分支和标签的 zero 支持。 Subversion 基本上说:我们查看了其他系统中的全功能分支和标签,但没有发现它们有用,所以我们没有实现任何东西。只需将副本复制到具有名称 约定而不是 的新目录中。那么当然每个人都可以自由地有稍微不同的约定。要了解 真实 标签和单纯的复制 + 命名约定之间的区别,请参阅 Wikipedia 条目 Subversion tags & branches


P
Peter Mortensen

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

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

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

我觉得相当混乱:一个对分支或标签一无所知的修订控制系统。从实现的角度来看,我认为 Subversion 创建“副本”的方式非常聪明,但我必须知道它是我所谓的leaky abstraction

或者我只是使用 CVS 太久了。


另一种观点是相反的情况,将标签的概念强加于颠覆的对象模型将是相反方向的泄漏抽象。我猜你知道,颠覆是对 CVS 的一种反应,一种“正确地做 CVS”的尝试。我找不到参考资料,但最初的颠覆设计者说他们故意 100% 抛弃标签的概念,分支和标签之间的区别纯粹是一个政策问题。如果团队想在颠覆的对象模型之上强加政策和约定,那就这样吧。这正是我们今天所拥有的。
d
denis phillips

我认为一些混淆来自标签的概念和 SVN 中的实现之间的差异。对于 SVN,标签是一个分支,它是一个副本。修改标签被认为是错误的,事实上,如果您尝试修改路径中带有 ../tags/.. 的任何内容,TortoiseSVN 等工具会警告您。


P
Peter Mortensen

我不太确定“标签”是什么,但分支是一个相当常见的源代码控制概念。

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

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

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

这是Wikipedia entry on branches,因为他们可能比我能更好地解释事情。 :)


U
Ujjwal

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

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

标签:每次我们发布部分可交付的产品类型的测试版时,我们都会为它制作一个标签。这为我们提供了当时可用的代码,如果在开发过程中的某个时间点需要,我们可以回到那个状态。


这是您的特定工作流程,一般不适用。
D
Desert Rose

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

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