标签与Git中的分支有何不同?我应该在这里使用哪个?

我很难理解如何在中使用标签分支

我刚刚将我们当前版本的代码从移动到,现在我将为特定功能处理该代码的子集。其他一些开发人员也将致力于此,但并非我们组中的所有开发人员都将关心此功能。我应该创建分支还是标签?在什么情况下我应该使用一个分支还是另一个?

264974 次浏览

标签可以是签名或未签名;从未签名的分支。

签名标签永远无法移动,因为它们以加密方式绑定(使用签名)到特定提交。未签名标签未绑定,可以移动它们(但移动标签不是正常用例)。

分支不仅可以移动到不同的提交,而且预计也可以这样做。你应该为你的本地开发项目使用分支。“在标签上”将工作提交到Git存储库是没有意义的。

标签代表某个特定分支的某个版本。分支代表一个单独的开发线程,可以与同一代码库上的其他开发工作同时运行。对一个分支的更改最终可能会合并回另一个分支以统一它们。

通常你会标签一个特定的版本,以便你可以重新创建它,例如这是我们运到XYZ公司的版本分支更多的是一种策略,在继续对其进行开发的同时,为特定版本的代码提供持续更新。你将在交付版本上创建一个分支,在主线上继续开发,但对代表交付版本的分支进行bug修复。最终,你将这些bug修复合并回主线中。通常你会同时使用分支和标记。您将有各种标签,这些标签可能适用于主线及其分支,沿着您可能想要重新创建的每个分支标记特定版本(例如交付给客户的版本)-用于交付,bug诊断等。

它实际上比这更复杂-或者像你想的那样复杂-但是这些例子应该让你了解其中的差异。

理论的角度来看:

  • 标签是给定修订的符号名称。它们总是指向相同的对象(通常:指向相同的修订版);它们不会改变。
  • 分支发展路线的符号名称。在分支之上创建新的提交。分支指针自然前进,指向越来越新的提交。

技术的角度来看:

  • 标签驻留在refs/tags/命名空间中,可以指向标记对象(带注释和可选的GPG签名标签)或直接指向提交对象(较少使用的本地名称轻量级标签),或者在非常罕见的情况下甚至指向树对象blob对象(例如GPG签名)。
  • 分支驻留在refs/heads/命名空间中,并且只能指向提交对象HEAD指针必须引用分支(符号引用)或直接引用提交(分离的HEAD或未命名分支)。
  • 远程跟踪分支驻留在refs/remotes/<remote>/命名空间中,并遵循远程存储库<remote>中的普通分支。

另见词汇表手册:

分支

“分支”是一个活动的开发线。分支上的最新提交被称为该分支的尖端。分支的尖端由分支头引用,随着分支上的额外开发完成,分支头向前移动。单个git存储库可以跟踪任意数量的分支,但您的工作树只与其中一个分支(“当前”或“已签出”分支)相关联,并且HEAD指向该分支。

标签

指向标签或提交对象的ref。与头相反,标签不会被提交更改。标签(不是标签对象)存储在$GIT_DIR/refs/tags/中。[…]。标签最常用于标记提交祖先链中的特定点。

标签对象

包含指向另一个对象的ref的对象,它可以像提交对象一样包含消息。它也可以包含(PGP)签名,在这种情况下,它被称为“签名标签对象”。

git寓言解释了典型的DVCS是如何创建的,以及为什么他们的创建者会这样做。此外,你可能想看看计算机科学家的Git;它解释了Git中每种类型的对象的作用,包括分支和标签。

您需要意识到,来自CVS的是,您在设置分支时不再创建目录
不再有“粘标签”(只能应用于一个文件)或“分支标签”。
分支和标签是Git中的两个不同对象,它们始终适用于所有存储库。

您将不再(这次使用SVN)必须显式地使用以下内容构建您的存储库:

branches
myFirstBranch
myProject
mySubDirs
mySecondBranch
...
tags
myFirstTag
myProject
mySubDirs
mySecondTag
...

该结构来自于CVS是审校制度而不是版本系统的事实(参见源代码控制与版本控制?)。
这意味着通过CVS的标签模拟分支,SVN的目录副本。

如果您习惯于结帐标签,您的问题是有意义的,并且开始在里面工作
你不应该;)
标签应该表示不可变内容,仅用于访问它,并保证每次都获得相同的内容。

在Git中,修订的历史是一系列提交,形成一个图表。
分支是该图的一条路径

x--x--x--x--x # one branch
\
--y----y # another branch
1.1
^
|
# a tag pointing to a commit
  • 如果您签出一个标签,您将需要创建一个分支才能从它开始工作。
  • 如果您签出一个分支,您将直接看到该分支的最新提交('HEAD')。

有关所有技术细节,请参阅Jakub Narbski的回答,但坦率地说,在这一点上,您不需要(还)所有细节;)

要点是:标记是指向提交的简单指针,您将永远无法修改其内容。您需要一个分支。


在您的案例中,每个开发人员都致力于特定功能:

  • 应该在各自的存储库中创建自己的分支
  • 跟踪来自同事存储库的分支(处理相同功能的分支)
  • 拉/推,以便与您的同行分享您的工作。

您可以只跟踪一个“官方”中央存储库的分支,而不是直接跟踪同事的分支,每个人都将他/她的工作推送到该存储库,以便集成和共享每个人为此特定功能的工作。

看起来最好的解释是标签充当只读分支。你可以使用分支作为标签,但你可能会无意中用新的提交更新它。只要标签存在,就保证指向相同的提交。

没有一个比喻是完美的,但是你可以把你的存储库想象成一本记录项目进展的书。

分支

你可以把一个分支想象成那些粘性的书签之一:

输入图片描述

一个全新的存储库只有一个(称为mastermain),它会自动移动到你编写的最新页面(想想提交)。但是,你可以自由创建和使用更多书签,以便标记书中的其他兴趣点,这样你就可以快速返回到它们。

此外,您始终可以将特定书签移动到书的其他页面(例如使用git-reset);兴趣点通常会随着时间的推移而变化。

标签

您可以将标签视为章标题

书签

它可能包含标题(想想注释标签)或不包含标题。标签与分支类似但不同,因为它标志着历史对本书感兴趣的一个点。为了保持其历史特征,一旦你共享了一个标签(即将其推送到共享远程),你不应该将其移动到书中的其他地方。

树枝由木头制成,从树干生长。标签由纸(木材的衍生物)制成,像圣诞装饰品一样悬挂在树上的各个地方。

您的项目是树,您将添加到项目中的功能将在一个分支上生长。答案是分支。

标签用于标记版本,更具体地说,它引用分支上的时间点。分支通常用于向项目添加功能。

简单:

标签应该总是指向项目的同一个版本,而头部应该随着开发的进展而前进。

Git用户手册

我喜欢把分支想象成你要去的地方标签想象成你去过的地方

标签感觉就像过去某个特定重要点的书签,例如版本发布。

而分支是项目正在下降的特定路径,因此分支标记与你一起前进。完成后,你合并/删除分支(即标记)。当然,在那一点上,你可以选择标记该提交。

简单的答案是:

分支: 当前分支指针随着每次提交到存储库而移动

标签:标签指向的提交不会改变,实际上标签是该提交的快照。

我们使用

  • branchesdev环境中进行功能开发或bug修复
  • lightweight tags用于功能分支上的test环境
  • annotated tags用于发布/PRD(主分支)

在每个带注释的标记之后,所有特征分支都从主分支重新定位。

正如其他人所说,branch是一条开发线,head随着新提交的到来而前进。这是功能开发的理想选择。

Lightweight tag已固定到特定的提交,这使得创建内部版本并让qa团队在开发完成后测试功能成为理想选择。

Annotated tag非常适合发布到生产环境,因为我们可以在将测试的功能分支合并到主分支(稳定)时添加正式消息和其他注释。

使用Git进行发布管理

github上的neovim:

v0.3是一个分支 输入图片描述

v0.3.1… v0.3.4…是标签

输入图片描述

夜间和稳定是标签,不是树枝

输入图片描述