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


615

我有一些困难,了解如何使用标签分支

我只是将代码的当前版本从 ,现在我将为特定功能处理该代码的子集。其他一些开发人员也将对此进行研究,但并非我们小组中的所有开发人员都将在意此功能。我应该创建分支还是标签?在什么情况下我应该使用一种而不是另一种?


4
由于在网上搜索如何使用git标签把我带到了这个链接首先,我补充一点,是关于一个标签一个更好的(恕我直言)答案在这里:stackoverflow.com/questions/35979642/...
阿列克谢Martianov

Answers:


519

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

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

实际上,它比这要复杂得多-或您想使其复杂得多-但这些示例应该使您对这些区别有所了解。


40
在他的情况下,他想使用分支,也许您也应该在回答中注意这一点;)
knittl

13
AFAIK,每个分支的标签不是唯一的。因此,您不能在单独的分支中为不同的提交使用相同的名称。
2012年

5
@MY当然不是一件坏事,恕我直言。尤其是按照tvanfosson所描述的方式,在不同分支上拥有多个具有相同名称的标签可能变得难以维护。给定示例,我认为如果您可以在不同分支中使用具有相同名称的标签,则会很快将其确定为不好的做法。很高兴知道您不能这样做。感谢我的!
2013年

28
标签只是提交哈希的别名。与可以检出提交相同,git checkout 88c9f229f您可以执行类似的操作,git checkout your_tag然后检出标记为别名的提交。
jterm

6
@jterm,分支别名不是吗?唯一的区别是分支别名自动将自身重新指向链中的最新提交。
维克多·莫洛科斯托夫

529

理论上讲

  • 标签是给定版本的符号名称。它们总是指向相同的对象(通常:指向相同的修订版);他们没有改变。
  • 分支开发线的象征性名称。在分支顶部创建新的提交。分支指针自然地前进,指向越来越新的提交。

技术角度来看:

  • 标签驻留在refs/tags/名称空间中,并且可以指向标签对象(带注释的和可选的GPG签名标签)或直接提交对象(对于本地名称使用较少的轻量级标签),或者在极少数情况下甚至指向树对象Blob对象(例如,GPG签名) )。
  • 分支位于refs/heads/名称空间中,并且只能指向commit对象。该HEAD指针必须引用分支(符号引用)或直接连接到一个提交(独立HEAD或无名分支)。
  • 远程跟踪分支驻留在refs/remotes/<remote>/名称空间中,并遵循远程存储库中的普通分支<remote>

另请参见gitglossary联机帮助页:

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

标签

指向标记或提交对象的引用。与头部不同,标签不会因提交而更改。标签(不是标签对象)存储在中$GIT_DIR/refs/tags/。[...]。标签最通常用于标记提交祖先链中的特定点。

标签对象

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


36
问题:如果将分支像标签一样对待(即创建它,然后再不更新它),那么有什么真正的区别吗?
史蒂夫·贝内特

30
@SteveBennett绝对。其中包含不同的信息(您可以在标签上签名,也可以在分支中添加描述)。您可以移动分支(因此,即使您从不更新它,也可以对其重新设置基准。)。您不能移动标签(它链接到特定的提交)。您可以选择推送分支。默认情况下不推送标签。永远不要将另一个用于另一个(除非您确实处于SVN思维模式中,否则,如果您要继续使用git,则需要快速“取消学习”)。
VonC'2

19
@SteveBennett:Git如何对待分支与如何对待标签是有区别的。除了VonC所说的之外,您不能错误地推进标签:“ git checkout <tag>”将生成匿名的未命名分支(即所谓的“分离头”)并选择标签状态。创建一个新的提交会在这个未命名的分支上执行它,并且不会更改标记指向的内容。
JakubNarębski2012年

60
IMO,分支是分开的时间轴(平行世界),而标记是时间轴上的特定时刻。
埃尼尔(Eonil)2012年

25
这里还没有人提到它,但是您可以使用标签作为开始分支的起点:git checkout -b <branch name> <tag name>

143

如果您将存储库视为一本记录项目进展的书...

分行

您可以将分支视为这些粘性书签之一

在此处输入图片说明

全新的存储库只有其中一个(称为master),该存储库会自动移至您编写的最新页面(请考虑commit)。但是,您可以自由创建和使用更多书签,以便在书中标记其他兴趣点,因此可以快速返回它们。

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

标签

您可以将标签视为章节标题

书签

它可能包含标题(不带注释标签)。标签与分支相似,但与分支不同,因为它标记了本书的历史兴趣点。为了保持其历史性,一旦共享了标签(即将其推送到共享的遥控器),就不应将其移动到书中的其他位置。


16
我想像一个分支将是一本书,书签是标签。您可以继续写书,但不能编辑。标签只是本书中的固定时间。
马丁斯Briedis

5
@Jubobs我喜欢分支的解释作为开发的一条线。一本书将是一个分支。您可以根据离开主分支的位置开始一本新书。您可以将它们并行编写,然后尝试合并到一本书/分支中。
马丁斯Briedis

2
@MārtiņšBriedis我了解您想分支的方式,但是我发现在Git中,这实际上是一种误导。参见stackoverflow.com/questions/25068543/…–
jub0bs

2
这真的是一个节省时间的答案
Ali Foroughi 2015年

2
如果您开始写书且头有50页,则可以对其进行复制(从中创建一个新分支),然后继续同时编写两本书(或将该书的副本提供给其他作家-开发人员),最后可以合并从另一本书更改为您的书。
barell

42

从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”)。

参见JakubNarębski的答案所有技术,但是坦率地说,在这一点上,您并不需要所有细节;)

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


对于您而言,每个开发人员都在使用特定功能:

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

除了直接跟踪同事的分支机构,您还可以跟踪每个人将其工作推送到一个“官方”中央存储库的分支机构,以便集成和共享每个人针对该特定功能的工作。


1
感谢您澄清分支和标签的工作方式:)如果没有您的示例,我将无法完全理解它。
ufk 2011年

3
@VonC:我认为您在回答中的意思是“ SVN”,而不是“ CVS”。CVS没有目录结构;SVN可以。实际上,在git中添加标签比在SVN中添加标签更能使我想到RCS / CVS中的添加标签(其中tag ==简并分支)。
克里斯·克莱兰

1
@ChrisCleeland好点。我试图在(编辑后的)答案中分离出更多的CVS和SVN点。
VonC 2012年

37

树枝是用木头制成的,从树的树干上长出来。标签由纸制成(木质衍生物),并像圣诞树上的圣诞节装饰品一样悬挂在树上的各个位置。

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


3
喜欢类比
doz87 '16

16

看起来最好的解释方式是标签充当只读分支。您可以将分支用作标记,但可能会无意中使用新的提交对其进行更新。只要标签存在,就可以保证它们指向同一提交。


11
只要标签存在,就可以保证它们指向同一提交。不完全正确。您实际上可以使用来移动标签git tag -f
jub0bs

14

标签可以是签名的也可以是未签名的;分支永远不会签名。

签名标签永远不会移动,因为它们是通过密码绑定(带有签名)的特定提交。未签名的标签没有绑定,可以移动它们(但移动标签不是正常的用例)。

分支不仅可以移至其他提交,而且有望这样做。您应该为本地开发项目使用一个分支。将工作“放在标签上”提交到Git存储库是没有意义的。


12

我喜欢将分支机构视为您要去的地方,将标签视为您去过的地方

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

分支是特定路径,项目正在下降,因此分支标记会随您前进。完成后,您可以合并/删除分支(即标记)。当然,此时您可以选择标记该提交。



6

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



4

简单的答案是:

分支:当前分支指针在每次提交到存储库时都会移动

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

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.