【问题标题】:Do git tags apply to all branches?git 标签是否适用于所有分支?
【发布时间】:2013-08-07 22:22:21
【问题描述】:

我被 git 标记弄湿了,但我之前的背景是在 Subversion 中,“标记”实际上只是副本,而不是“真正的”标记...

如果我在 git repo 中添加标签,它是应用于所有分支还是仅应用于当前分支?

例如,如果我目前有这些分支 (git branch -v):

* master deadbeef My master head comment
  dev    baddfeed My def head comment

如您所见,当前签出的分支是 master。现在假设我git tag -a TAGNAMETAGNAME 是否只适用于deadbeef(主分支)或baddfeed(开发分支)?

例如,假设我随后在签出标签之前切换到 dev 分支(即,不是创建标签的分支):

git checkout dev
git checkout TAGNAME

然后我是否会结帐baddfeed 或者标记结帐(第二行)会将我切换回主分支(创建标记的位置)并给我结帐deadbeef? (或者第三个选项,我对创建和恢复标签的理解是否过于有缺陷或过于简单,以至于答案不能像这两个选项之一那样简单?)

另外,如果我使用轻量级标签 (git tag TAGNAME) 而不是带注释的标签,我的问题的答案是否会改变?

【问题讨论】:

标签: git branch git-branch git-tag


【解决方案1】:

为了简单起见:

如果我在 git repo 中添加标签,它是应用于所有分支还是仅应用于当前分支?

在 Git 中,标签只是提交 ID 的别名。当您添加标签时,Git 只是将您的标签名称(标签字符串)映射到给定的提交 ID。由于提交 id 与特定分支(或合并时的分支)相关,因此标签将仅与该分支(以及合并到的任何分支)相关。

更多信息可以在这里找到:

http://git-scm.com/book/en/Git-Basics-Tagging#Creating-Tags

【讨论】:

    【解决方案2】:

    阅读了问题和您的 cmets,我认为让您感到困惑的基本点是在 git(相对于其他系统)中“在分支上”的含义。

    在 git 中,git checkout 操作会检查一些特定的提交 [但请参见脚注 1]。它还设置了特殊名称HEAD,以便它引用该特定提交。但是:HEAD 可以通过两种不同的方式指定特定的提交。可以是:

    • 按 ID(这是通常的情况),或
    • 间接引用分支名称(这是更常见的情况)。

    如果你使用git checkout <i>branchname</i>,git 会设置第二种,通常情况。如果你然后cat .git/refs/HEAD,你会发现它包含文字字符串ref:,后跟refs/heads/<i>branchname</i> [2]。这就是“在分支上”的含义:您已经检查了分支名称所指的提交,而且HEAD 是一个“符号引用”。如果您进行新的更改并提交它们,git 将进行新的提交,然后“剥离”分支标签便笺并将其粘贴到您刚刚添加的新提交上。这会将分支“移动”到新添加的提示,而您“仍在分支上”。

    另一方面,如果你执行git checkout <i>tagname</i>,git 会设置第一个异常情况。如果您通过 SHA-1 ID(那些ea56709... 样式字符串)签出,它的作用相同。在这种情况下,HEAD 的文件中只有文字 SHA-1 ID。在这种状态下,如果您进行新的提交,它会像往常一样被添加,但不会更改便笺来移动分支标签。你不是“在树枝上”; HEAD 不是“符号引用”。

    就实际标签本身而言,它们只是提交的名称。但是等等,这不是分支名称吗?是的!分支名称和标签名称之间的区别在于,分支名称是预计要移动的,git 会在“分支上”的情况下自动移动它。标签名称不是“预计会移动”[3],并且永远不会自动移动。


    脚注:

    [1] 只是为了混淆事物(或者因为 git 的用户界面是“邪恶的”,就像有些人会说的那样 :-))有些情况 git checkout 不会改变 HEAD,特别是当你要求它检查特定的路径名​​。

    [2] 在非常旧的 git 版本中,git 使用符号链接而不是 ref: ...。链接的目标是分支 ID 文件,例如 refs/heads/master 或其他任何内容,因此打开和读取文件会获得提交 ID,您必须使用 lstat 来检测“在分支上”。这在 Windows 上不起作用,并且排除了“打包”引用 (.git/packed-refs),因此改为使用 ref:

    [3] 短语“预期”和“不预期”应该提示您问:预期由谁? Git 本身对 git 用户移动标签没问题,使用 git 的人(通常是他们编写的脚本)对此感到困惑。所以不要移动标签,除非您首先与共享存储库的其他人核对过。

    【讨论】:

    • 哇,我见过的标签的最佳解释,谢谢 matser
    【解决方案3】:

    假设您在分支myBranch。然后创建一个名为myTag的标签

    -----A-----B-----C-----D-----H-------I-----> master
                           \
                            \
                             \---E----F-----G-----> myBranch
                                            |
                                            myTag
    

    标签只会出现在myBranch 分支的提交对象上。我也使用过 CVS,它也标记了修订,不是所有的分支(但在 CVS 分支中是特殊标记)。我不认为。

    如果您签出myTag,您将在示例的提交G 中。您不能在不同的分支上创建具有相同名称的标签。如果你这样做,你会移动标签。

    与此相关的带注释标签没有区别。

    注意:签出标签时,您会以“分离 HEAD”模式结束。除非您从签出的标签开始创建另一个分支,否则您的更改将会丢失。

    【讨论】:

    • 谢谢,这很清楚。所以只是为了结束循环,如果我在我的 OQ 中给出命令序列(即git checkout dev; git checkout TAGNAME),那么我最终会回到 master 分支,并签出 deadbeef 提交在分离模式下(即使它碰巧仍然是主人的头,它会被分离检出);对吗?
    • 从技术上讲,以“分离 HEAD”模式添加的提交不会丢失:它们只是没有方便的名称,因此您必须使用原始 SHA-1 ID。您可以事后粘贴分支名称。这样做只是一种痛苦。 (另外,一段时间后——默认为 90 天——如果它们仍然没有“好”的名字,它们将被垃圾收集。)
    • @DaveLillethun 是的。你将再次成为大师。即使提交是 HEAD,您也会处于分离的 HEAD 模式。
    • @torek 你是对的。我同意你的观点:“这样做很痛苦。”。万一有人来到这里并且对如何获取这些“丢失”提交的提交 ID 感到好奇,请使用 git reflog
    猜你喜欢
    • 2013-01-14
    • 2011-08-07
    • 2015-04-26
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 2012-08-21
    相关资源
    最近更新 更多