ChatGPT解决这个技术问题 Extra ChatGPT

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

我在理解如何在 中使用 tagsbranches 时遇到了一些困难。

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

由于网络搜索如何使用 git tag 首先将我带到该链接,我补充说这里有一个关于标签的更好(恕我直言)答案:stackoverflow.com/questions/35979642/…

j
jskroch

从理论上看:

标签是给定版本的符号名称。它们总是指向同一个对象(通常:指向同一个版本);他们不会改变。

分支是开发线的符号名称。新的提交是在分支之上创建的。分支指针自然地前进,指向越来越新的提交。

从技术角度:

标签驻留在 refs/tags/ 命名空间中,可以指向标签对象(带注释的和可选的 GPG 签名标签)或直接提交对象(较少使用的本地名称轻量级标签),或者在极少数情况下甚至指向树对象或 blob 对象(例如 GPG 签名)。

分支位于 refs/heads/ 命名空间中,并且只能指向提交对象。 HEAD 指针必须指向一个分支(符号引用)或直接指向一个提交(分离的 HEAD 或未命名的分支)。

远程跟踪分支位于 refs/remotes// 命名空间中,并遵循远程存储库 中的普通分支。

另请参阅 gitglossary 手册页:

分支 “分支”是一条活跃的开发线。分支上的最新提交称为该分支的尖端。分支的尖端由分支头引用,随着在分支上完成额外的开发,它会向前移动。单个 git 存储库可以跟踪任意数量的分支,但您的工作树仅与其中一个关联(“当前”或“签出”分支),并且 HEAD 指向该分支。 tag 指向标签或提交对象的引用。与头相比,提交不会更改标签。标签(不是标签对象)存储在 $GIT_DIR/refs/tags/ 中。 [...]。标签最常用于标记提交祖先链中的特定点。标记对象 包含指向另一个对象的 ref 的对象,该对象可以包含消息,就像提交对象一样。它还可以包含(PGP)签名,在这种情况下,它被称为“签名标签对象”。


问题:如果您将分支视为标签(也就是说,您创建它,然后从不更新它),有什么真正的区别吗?
@SteveBennett 绝对。其中包含不同的信息(您可以签署标签,可以向分支添加描述)。你可以移动一个分支(所以即使你从不更新它,你仍然可以重新设置它。)。您不能移动标签(它链接到特定的提交)。您可以选择推送分支。默认情况下不推送标签。你永远不应该将一个用于另一个(除非你真的处于 SVN 心态,在这种情况下,如果你想继续使用 git,你需要快速“取消学习”)。
@SteveBennett:Git 处理分支的方式与处理标签的方式有所不同。除了VonC所说的,你不能错误地推进标签:“git checkout <tag>”会生成匿名的未命名分支(所谓的'分离的HEAD')并选择标签的state。在这个未命名的分支上创建一个新的提交,并且不会更改标记指向的内容。
IMO,分支是分开的时间线(平行世界),标签是时间线上的特定时刻。
这里还没有人提到它,但您可以使用标签作为开始分支的点:git checkout -b <branch name> <tag name>
S
StackzOfZtuff

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

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

它实际上比这更复杂——或者像你想要的那样复杂——但这些例子应该让你了解它们之间的区别。


在他的情况下,他想使用分支,也许您还应该在回答中注意这一点;)
AFAIK,每个分支的标签都不是唯一的。所以你不能在不同的分支中为不同的提交提供相同的名称。
@MY 当然不是坏事,恕我直言。特别是按照 tvanfosson 所描述的方式,在不同的分支中拥有多个同名标签可能会变得难以维护。鉴于这个例子,我认为如果你可以在不同的分支中拥有相同名称的标签,那么它很快就会被确立为一种不好的做法。不过,很高兴知道你不能。感谢我的!
标签只是提交哈希的别名。与您可以使用 git checkout 88c9f229f 签出提交一样,您可以执行 git checkout your_tag 之类的操作,您将签出由标签别名的提交。
@jterm,分支也不是别名吗?唯一的区别是分支别名会自动将自己重新指向链中最近的提交。
L
Lance Kind

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

分支机构

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

https://i.stack.imgur.com/fpx8U.png

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

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

标签

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

https://i.stack.imgur.com/s3TWI.png

它可能包含标题(想想 annotated tags)或不包含。标签与分支相似但不同,因为它标记了本书中历史的兴趣点。为了保持其历史特征,一旦您共享了一个标签(即将其推送到共享遥控器),you're not supposed to 将其移动到书中的其他位置。


我会想象一个分支是一本书,而书签是标签。你可以继续写一本书,但你不能编辑它。标签只是书中的一个固定时刻。
@Jubobs 我喜欢将分支解释作为开发线。一本书将是一个分支。您可以根据离开主分支的位置开始新书。您可以并行编写它们,然后尝试合并到一本书/分支中。
@MārtiņšBriedis 我理解您对分支的看法,但我发现在 Git 中这实际上是一种误导。请参阅stackoverflow.com/questions/25068543/…
这真的是一个节省时间的答案
如果你开始写一本书并且你有前 50 页,你可以复制它(从它创建一个新的分支)并继续同时写两本书(或者把这本书的副本交给其他作家 - 开发人员),最后你可以合并从另一本书更改为您的书。
C
Community

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

您将不再(这次使用 SVN)必须明确地构建您的存储库:

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

这种结构源于 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

如果你签出一个标签,你需要创建一个分支来开始工作。

如果您签出一个分支,您将直接看到该分支的最新提交它('HEAD')。

有关所有技术细节,请参阅 Jakub Narębski's answer,但坦率地说,此时,您不需要(还)所有详细信息;)

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

就您而言,每个开发特定功能的开发人员:

应该在各自的存储库中创建自己的分支

从他们同事的存储库中跟踪分支(使用相同功能的存储库)

拉/推,以便与同行分享您的工作。

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


@VonC:我认为您的答案是“SVN”,而不是“CVS”。 CVS 没有目录结构; SVN 可以。事实上,在 git 中进行标记比在 SVN 中标记(其中标记 == 退化分支)更让我想起 RCS/CVS 中的标记。
@ChrisCleeland 好点。我试图在(编辑的)答案中分离更多的 CVS 和 SVN 点。
J
Jason

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

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


喜欢这个比喻
V
Vassili Gorshkov

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


标签只要存在就保证指向同一个提交。 不完全正确。您实际上可以使用 git tag -f 移动标签。
G
Gazzer

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

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

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


G
Greg Hewgill

标签可以是 signed or unsigned;分支永远不会签名。

签名标签永远不能移动,因为它们被加密绑定(带有签名)到特定的提交。未签名的标签未绑定并且可以移动它们(但移动标签不是正常的用例)。

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


j
jsina

简单的答案是:

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

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


j
jub0bs

Git Parable 解释了典型的 DVCS 是如何创建的,以及他们的创建者为何这样做。此外,您可能想看看 Git for Computer Scientist;它解释了 Git 中每种类型的对象的作用,包括分支和标签。


N
Number45

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


A
Adeel

简单的:

预计标签始终指向项目的同一版本,而负责人预计会随着开发的进展而前进。

Git User Manual


3
3 revs

我们用

开发环境中的分支,用于功能开发或错误修复

功能分支上测试环境的轻量级标签

release/prd(主分支)的注释标签

在每个带注释的标签之后,所有功能分支都从主分支变基。

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

Lightweight tag 固定为特定的提交,因此非常适合创建内部版本并让 qa 团队在开发完成后测试功能。

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

https://i.stack.imgur.com/yGnWt.png


G
Good Pen

github上的neovim:

https://i.stack.imgur.com/mkpnD.png

v0.3.1 ... v0.3.4 ... 是标签

https://i.stack.imgur.com/TBcsu.png

nightly 和 stable 是标签,而不是分支

https://i.stack.imgur.com/Ls16d.png