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

Bia*_*cki 593 git version-control branch git-tag git-branch

我在理解如何在使用标签分支时遇到一些困难.

我刚刚将当前版本的代码从,现在我将为特定功能处理该代码的子集.其他一些开发人员也会参与其中,但并非所有开发人员都会关注此功能.我应该创建分支还是标记?在什么情况下我应该使用一个与另一个?

Jak*_*ski 515

理论的角度来看:

  • 标签是给定修订的符号名称.它们总是指向同一个对象(通常是指同一个版本); 他们不会改变.
  • 分支发展线的象征性名称.在分支上创建新提交.分支指针自然地前进,指向更新和更新的提交.

技术角度来看:

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

另见gitglossary联机帮助页:

"分支"是一个积极的发展路线.分支上的最新提交称为该分支的提示.分支的尖端由分支头引用,分支头在分支上进行额外的开发时向前移动.单个git存储库可以跟踪任意数量的分支,但是您的工作树只与其中一个分支相关联("当前"或"已检出"分支),HEAD指向该分支.

标签

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

标签对象

包含指向另一个对象的ref的对象,该对象可以包含与提交对象类似的消息.它还可以包含(PGP)签名,在这种情况下,它被称为"签名标记对象".

  • IMO,分支是分开的时间轴(并行世界),标签是时间轴上的特定时刻. (53认同)
  • 问题:如果您将分支视为标记(即,您创建它,然后永远不更新它),是否有任何真正的区别? (35认同)
  • @SteveBennett绝对.包含不同的信息(您可以对标签进行签名,您可以向分支添加说明).你可以移动一个分支(所以即使你永远不更新它,你仍然可以改变它.).您无法移动标记(它链接到特定的提交).你可以选择推分支.默认情况下不会推送标签.你永远不应该使用一个用于另一个(除非你真的处于SVN心态,在这种情况下你需要快速"取消学习",如果你想继续使用git). (29认同)
  • 这里没有人提到它,但你可以使用标签作为开始分支的点:`git checkout -b <branch name> <tag name>` (24认同)
  • @SteveBennett:Git如何处理分支与处理标签的方式有所不同.除了VonC所说的,你不能错误地推进标签:"`git checkout <tag>`"将生成匿名的未命名分支(所谓的'分离的HEAD')并选择标签的_state_.创建新提交会在此未命名分支上执行,并且不会更改标记指向的标记. (18认同)
  • @KenStailey:您可以使用_any_ commit(任何修订版)作为分支的起点; 使用标签只是这种情况的一个特例. (4认同)
  • @VonC我发现你的评论比你的第一个答案更有用/更简洁,也就是说,当标签不是时,分支会被重新定位. (2认同)

tva*_*son 496

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

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

它实际上比这更复杂 - 或者像你想要的那样复杂 - 但是这些例子可以让你了解这些差异.

  • 在他的情况下,他想使用分支机构,也许你应该在你的答案中注意到这一点;) (38认同)
  • 标记只是提交哈希的别名.与使用`git checkout 88c9f229f`签出提交相同,您可以执行类似`git checkout your_tag`的操作,并且您将检查由标记别名的提交. (23认同)
  • AFAIK,每个分支的标签不是唯一的.所以你不能在不同的分支中为不同的提交给出相同的名称. (13认同)
  • @jterm,也不是分支别名吗?唯一的区别是分支别名会自动将自身重新发布到链中的最新提交. (6认同)
  • @MY当然不是坏事,恕我直言.特别是以tvanfosson描述的方式,在不同分支中具有多个具有相同名称的标签可能变得难以维护.举个例子,我认为如果你*可以*在不同的分支上有相同名称的标签,很快就会被认为是一种不好的做法.很高兴知道你不能.感谢我的! (5认同)

jub*_*0bs 140

如果您认为您的存储库是一本记录您项目进度的书籍......

分行

您可以将分支视为其中一个粘性书签:

在此输入图像描述

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

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

标签

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

书签

它可能包含标题(思考注释标签).标签类似但与分支不同,因为它标志着书中的历史兴趣点.为了保持其历史方面,一旦您共享了一个标签(即将其推送到共享遥控器),您就不应该将其移动到书中的其他位置.

  • 我想象一个分支是一本书,书签是标签.您可以继续写书,但不能编辑它.标签只是书中固定的时刻. (13认同)
  • @Jubobs我喜欢分支解释作为开发线.一本书就是一个分支.您可以根据主分支离开的位置开始新书.您可以将它们写成并行,然后尝试合并到一本书/分支. (5认同)
  • @MārtiņšBriedis我理解你想要分支的方式,但我发现,在Git中,这实际上是误导性的.请参阅http://stackoverflow.com/questions/25068543/what-exactly-do-we-mean-by-branch (2认同)
  • 这个真的是节省时间的答案 (2认同)
  • 如果你开始写一本书并且你有前50页,你可以复制它(从中创建一个新的分支)并继续同时写两本书(或将书籍副本交给其他作家 - 开发人员)最后你可以合并从另一本书改为你的书. (2认同)

Von*_*onC 42

来自CVS的您需要意识到的是,在设置分支时不再创建目录.
不再有"粘性标签"(可以只应用于一个文件)或"分支标签".
分支和标签是Git中的两个不同对象,它们总是适用于所有 repo.

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

branches
   myFirstBranch
     myProject
       mySubDirs
   mySecondBranch
     ...
tags
   myFirstTag
     myProject
       mySubDirs
   mySecondTag
   ...
Run Code Online (Sandbox Code Playgroud)

该结构来自CVS是修订系统而不是版本系统(参见Source control vs. Revision Control?).
这意味着分支通过CVS的标签模拟,SVN的目录副本.

如果您习惯于签出标签,并且开始使用标签,那么您的问题就会有所体现.
你不应该这样;)
标签应该代表一个不可变的内容,仅用于访问它,并保证每次都获得相同的内容.

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

x--x--x--x--x # one branch
    \ 
     --y----y # another branch
       1.1
        ^
        |
        # a tag pointing to a commit
Run Code Online (Sandbox Code Playgroud)
  • 如果签出标签,则需要创建一个分支以开始使用它.
  • 如果你签出一个分支,你将直接看到该分支的最新提交('HEAD').

请参阅JakubNarębski对所有技术细节的回答,但坦率地说,此时,您不需要(还)所有细节;)

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


在您的情况下,每个开发人员都在处理特定功能:

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

您可以只跟踪一个"官方"中央存储库的分支,而不是直接跟踪同事的分支,每个人都推动他/她的工作,以便集成和共享每个人为这个特定功能工作的工作.

  • @VonC:我认为你的答案中的意思是"SVN"而不是"CVS".CVS没有目录结构; SVN呢.实际上,git中的标记让我想起了RCS/CVS中的标记,而不是SVN中的标记(其中tag == degenerate branch). (3认同)

小智 37

树枝由木头制成,从树干生长.标签由纸(木材的衍生物)制成,并且像树上的不同地方的圣诞饰品一样悬挂.

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

  • 喜欢类比 (3认同)

小智 16

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

  • *只要它们存在,标签就保证指向相同的提交.*不完全正确.您实际上可以使用`git tag -f`移动标记. (11认同)

Gre*_*ill 14

标签可以是签名的也可以是未签名的 ; 分支从未签署.

签名标签永远不会移动,因为它们以加密方式绑定(带有签名)到特定提交.未签名的标签没有绑定,可以移动它们(但移动标签不是正常的用例).

分行不仅可以移动到不同的提交但预计这样做.您应该为本地开发项目使用分支.将工作提交到"标记"上的Git存储库是没有意义的.


Bom*_*mbe 10

Git的比喻解释了如何一个典型的DVCS被创建,为什么它们的创造者做他们做了什么.另外,你可能想看看Git for Computer Scientist ; 它解释了Git中每种类型的对象的作用,包括分支和标记.


jsi*_*ina 10

简单的答案是:

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

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


Gaz*_*zer 9

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

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

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


Num*_*r45 6

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


Bar*_*ing 6

简单的:

标签应始终指向项目的同一版本,而标头应随着开发的进展而前进。

Git 用户手册


归档时间:

查看次数:

195829 次

最近记录:

6 年 前