我很难理解如何在git中使用标签与分支。
我刚刚将我们当前版本的代码从cvs移动到git,现在我将为特定功能处理该代码的子集。其他一些开发人员也将致力于此,但并非我们组中的所有开发人员都将关心此功能。我应该创建分支还是标签?在什么情况下我应该使用一个分支还是另一个?
标签可以是签名或未签名;从未签名的分支。
签名标签永远无法移动,因为它们以加密方式绑定(使用签名)到特定提交。未签名标签未绑定,可以移动它们(但移动标签不是正常用例)。
分支不仅可以移动到不同的提交,而且预计也可以这样做。你应该为你的本地开发项目使用分支。“在标签上”将工作提交到Git存储库是没有意义的。
标签代表某个特定分支的某个版本。分支代表一个单独的开发线程,可以与同一代码库上的其他开发工作同时运行。对一个分支的更改最终可能会合并回另一个分支以统一它们。
通常你会标签一个特定的版本,以便你可以重新创建它,例如这是我们运到XYZ公司的版本。分支更多的是一种策略,在继续对其进行开发的同时,为特定版本的代码提供持续更新。你将在交付版本上创建一个分支,在主线上继续开发,但对代表交付版本的分支进行bug修复。最终,你将这些bug修复合并回主线中。通常你会同时使用分支和标记。您将有各种标签,这些标签可能适用于主线及其分支,沿着您可能想要重新创建的每个分支标记特定版本(例如交付给客户的版本)-用于交付,bug诊断等。
它实际上比这更复杂-或者像你想的那样复杂-但是这些例子应该让你了解其中的差异。
从理论的角度来看:
从技术的角度来看:
refs/tags/
refs/heads/
HEAD
refs/remotes/<remote>/
<remote>
另见词汇表手册:
分支 “分支”是一个活动的开发线。分支上的最新提交被称为该分支的尖端。分支的尖端由分支头引用,随着分支上的额外开发完成,分支头向前移动。单个git存储库可以跟踪任意数量的分支,但您的工作树只与其中一个分支(“当前”或“已签出”分支)相关联,并且HEAD指向该分支。 标签 指向标签或提交对象的ref。与头相反,标签不会被提交更改。标签(不是标签对象)存储在$GIT_DIR/refs/tags/中。[…]。标签最常用于标记提交祖先链中的特定点。 标签对象 包含指向另一个对象的ref的对象,它可以像提交对象一样包含消息。它也可以包含(PGP)签名,在这种情况下,它被称为“签名标签对象”。
分支
“分支”是一个活动的开发线。分支上的最新提交被称为该分支的尖端。分支的尖端由分支头引用,随着分支上的额外开发完成,分支头向前移动。单个git存储库可以跟踪任意数量的分支,但您的工作树只与其中一个分支(“当前”或“已签出”分支)相关联,并且HEAD指向该分支。
标签
指向标签或提交对象的ref。与头相反,标签不会被提交更改。标签(不是标签对象)存储在$GIT_DIR/refs/tags/中。[…]。标签最常用于标记提交祖先链中的特定点。
$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
有关所有技术细节,请参阅Jakub Narbski的回答,但坦率地说,在这一点上,您不需要(还)所有细节;)
要点是:标记是指向提交的简单指针,您将永远无法修改其内容。您需要一个分支。
在您的案例中,每个开发人员都致力于特定功能:
您可以只跟踪一个“官方”中央存储库的分支,而不是直接跟踪同事的分支,每个人都将他/她的工作推送到该存储库,以便集成和共享每个人为此特定功能的工作。
看起来最好的解释是标签充当只读分支。你可以使用分支作为标签,但你可能会无意中用新的提交更新它。只要标签存在,就保证指向相同的提交。
没有一个比喻是完美的,但是你可以把你的存储库想象成一本记录项目进展的书。
你可以把一个分支想象成那些粘性的书签之一:
一个全新的存储库只有一个(称为mastermain),它会自动移动到你编写的最新页面(想想提交)。但是,你可以自由创建和使用更多书签,以便标记书中的其他兴趣点,这样你就可以快速返回到它们。
master
main
此外,您始终可以将特定书签移动到书的其他页面(例如使用git-reset);兴趣点通常会随着时间的推移而变化。
git-reset
您可以将标签视为章标题。
它可能包含标题(想想注释标签)或不包含标题。标签与分支类似但不同,因为它标志着历史对本书感兴趣的一个点。为了保持其历史特征,一旦你共享了一个标签(即将其推送到共享远程),你不应该将其移动到书中的其他地方。
树枝由木头制成,从树干生长。标签由纸(木材的衍生物)制成,像圣诞装饰品一样悬挂在树上的各个地方。
您的项目是树,您将添加到项目中的功能将在一个分支上生长。答案是分支。
标签用于标记版本,更具体地说,它引用分支上的时间点。分支通常用于向项目添加功能。
简单:
标签应该总是指向项目的同一个版本,而头部应该随着开发的进展而前进。
Git用户手册
我喜欢把分支想象成你要去的地方,标签想象成你去过的地方。
标签感觉就像过去某个特定重要点的书签,例如版本发布。
而分支是项目正在下降的特定路径,因此分支标记与你一起前进。完成后,你合并/删除分支(即标记)。当然,在那一点上,你可以选择标记该提交。
简单的答案是:
分支: 当前分支指针随着每次提交到存储库而移动
但
标签:标签指向的提交不会改变,实际上标签是该提交的快照。
我们使用
branches
dev
lightweight tags
test
annotated tags
在每个带注释的标记之后,所有特征分支都从主分支重新定位。
正如其他人所说,branch是一条开发线,head随着新提交的到来而前进。这是功能开发的理想选择。
branch
head
Lightweight tag已固定到特定的提交,这使得创建内部版本并让qa团队在开发完成后测试功能成为理想选择。
Lightweight tag
Annotated tag非常适合发布到生产环境,因为我们可以在将测试的功能分支合并到主分支(稳定)时添加正式消息和其他注释。
Annotated tag
github上的neovim:
v0.3是一个分支
v0.3.1… v0.3.4…是标签
夜间和稳定是标签,不是树枝