【问题标题】:What is git tag, How to create tags & How to checkout git remote tag(s)什么是 git 标签,如何创建标签以及如何签出 git 远程标签
【发布时间】:2016-06-29 00:36:22
【问题描述】:

当我签出远程 git 标签时,使用如下命令:

git checkout -b local_branch_name origin/remote_tag_name

我收到这样的错误:

错误:pathspec origin/remote_tag_name 与 git 已知的任何文件都不匹配。

使用 git tag 命令可以找到 remote_tag_name。

【问题讨论】:

标签: git git-checkout git-tag


【解决方案1】:

我们先来解释一下git中的标签是什么

标签用于标记和标记历史记录中的特定提交
它通常用于标记发布点(例如 v1.0 等)。

虽然标签可能看起来类似于分支,但标签不会改变。它直接指向历史记录中的特定提交,除非明确更新,否则不会更改。


如果标签不在本地存储库中,您将无法签出标签,因此首先,您必须将标签 fetch 到本地存储库。

首先,确保标签在本地存在

# --all will fetch all the remotes.
# --tags will fetch all tags as well
$ git fetch --all --tags --prune

然后通过运行检查标签

$ git checkout tags/<tag_name> -b <branch_name>

使用tags/ 前缀代替origin


在此示例中,您有 2 个 1.0 版和 1.1 版标签,您可以使用以下任何一种方式检查它们:

$ git checkout A  ...
$ git checkout version 1.0  ...
$ git checkout tags/version 1.0  ...

以上所有内容都将执行相同的操作,因为标记只是指向给定提交的指针。


来源:https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


如何查看所有标签的列表?

# list all tags
$ git tag

# list all tags with given pattern ex: v-
$ git tag --list 'v-*'

如何创建标签?

创建标签有两种方式:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

两者之间的区别在于,在创建带注释的标签时,您可以像在 git commit 中一样添加元数据:
姓名、电子邮件、日期、评论和签名

如何删除标签?

删除本地标签

$ git tag -d <tag_name>
Deleted tag <tag_name> (was 000000)

注意:如果你尝试删除一个不存在的Git标签,将会看到如下错误:

$ git tag -d <tag_name>
error: tag '<tag_name>' not found.

删除远程标签

# Delete a tag from the server with push tags
$ git push --delete origin <tag name>

如何克隆特定标签?

为了获取给定标签的内容,您可以使用checkout 命令。如上所述,标签与任何其他提交一样,因此我们可以使用 checkout 而不是使用 SHA-1,只需将其替换为 tag_name

选项 1:

# Update the local git repo with the latest tags from all remotes
$ git fetch --all

# checkout the specific tag
$ git checkout tags/<tag> -b <branch>

选项 2:

使用克隆命令

由于 git 支持 浅克隆,通过将 --branch 添加到克隆命令中,我们可以使用标签名称而不是分支名称。 Git 知道如何将给定的 SHA-1 “翻译”为相关的提交

# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

git clone --branch=

--branch 还可以在结果存储库中的该提交处获取标签并分离 HEAD。


如何推送标签?

git push --tags

推送所有标签:

# Push all tags
$ git push --tags 

使用refs/tags 而不是仅仅指定&lt;tagname&gt;

为什么?

  • 建议使用refs/tags,因为有时标签可以与您的分支同名,简单的 git push 会推送分支而不是标签

要推送带注释的标签和当前历史链标签,请使用:

git push --follow-tags

此标志--follow-tags 同时推送 commitsonly tags,它们都是:

  • 带注释的标签(因此您可以跳过本地/临时构建标签)
  • 当前分支(位于历史记录中)的可达标签(祖先)

从 Git 2.4 开始,您可以使用配置进行设置

$ git config --global push.followTags true

备忘单:


【讨论】:

  • 不错。 git checkout AA 是什么?你是如何创建A的?
  • @Honey A 是一个提交哈希
  • @GiovanniLovato 流程图是第三方的。图片的链接是backlog.com/git-tutorial/img/post/stepup/…,来自名为Git Beginner's Guide for Dummies (backlog.com) 的网站backlog.com/git-tutorial/stepup/stepup4_1.html
  • 值得注意的是git checkout tags/&lt;tag_name&gt; -b &lt;branch_name&gt; 确实需要-b &lt;branch_name&gt;git checkout tags/&lt;tag_name&gt; 给了我一个超然的脑袋。根据这个article about detached head,您可以通过临时创建和删除分支来避免分离头。这是一个非常陌生的工作流程。显然,我作为一个 git 用户需要习惯于创建和删除分支以获得乐趣和利润。
  • 我会说轻量级标签而不是普通标签。在许多存储库中,带注释的标签是常态。
【解决方案2】:

(这个答案写了好久,codeWizard's answer在目的和本质上是正确的,但并不完全,所以我还是会发布这个。)


没有所谓的“远程 Git 标签”。只有“标签”。我指出这一切并不是学究气,1 但因为对于普通 Git 用户来说,这有很多困惑,而且 Git 文档也不是很有帮助2给初学者。 (不清楚是因为文档质量差导致混乱,还是文档质量差是因为这本质上有点令人困惑,或者是什么。)

“远程分支”,更恰当地称为“远程跟踪分支”,但值得注意的是,这些实际上是本地实体。但是,没有远程标签(除非您(重新)发明它们)。只有本地标签,所以需要在本地获取标签才能使用。

特定提交名称的一般形式——Git 称之为references——是任何以refs/ 开头的字符串。以refs/heads/ 开头的字符串命名一个分支;以refs/remotes/ 开头的字符串命名远程跟踪分支;以refs/tags/ 开头的字符串命名一个标签。名称 refs/stash 是存储引用(git stash 使用的名称;注意缺少尾部斜杠)。

有一些不以refs/ 开头的不寻常的特殊情况名称:HEADORIG_HEADMERGE_HEADCHERRY_PICK_HEAD 尤其是所有可能引用特定提交的名称(尽管HEAD 通常包含分支的名称,即包含ref: refs/heads/<em>branch</em>)。但一般来说,引用以refs/ 开头。

Git 让这件事变得混乱的一件事是,它允许您省略 refs/,通常是 refs/ 之后的单词。例如,您可以在引用本地分支或标签时省略 refs/heads/refs/tags/ — 事实上,当签出本地分支时,您必须 省略 refs/heads/!只要结果明确,或者——正如我们刚刚提到的——当你必须这样做时,你都可以这样做(对于git checkout <em>branch</em>)。

确实,引用不仅存在于您自己的存储库中,还存在于远程存储库中。但是,Git 只允许您在非常特定的时间访问远程存储库的引用:即在 fetchpush 操作期间。您也可以使用git ls-remotegit remote show 来查看它们,但fetchpush 是更有趣的联系方式。

参考规范

fetchpush 期间,Git 使用它调用的字符串 refspecs 在本地和远程存储库之间传输引用。因此,正是在这些时候,通过 refspecs,两个 Git 存储库可以相互同步。一旦您的姓名同步,您就可以使用与遥控器相同的姓名。不过,fetch 有一些特殊的魔力,它会影响分支名称和标签名称。

您应该将git fetch 视为指示您的 Git 调用(或者可能是文本消息)另一个 Git(“远程”)并与之对话。在此对话的早期,遥控器列出了它的所有引用:refs/heads/ 中的所有内容和refs/tags/ 中的所有内容,以及它拥有的任何其他引用。您的 Git 会扫描这些并(基于通常的 fetch refspec)重命名它们的分支。

让我们看一下名为origin的遥控器的正常参考规范:

$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$ 

此 refspec 指示您的 Git 获取与 refs/heads/* 匹配的每个名称 - 即远程上的每个分支 - 并将其名称更改为 refs/remotes/origin/*,即保持匹配的部分相同,更改分支名称 (@987654360 @) 到远程跟踪分支名称(refs/remotes/,具体来说,refs/remotes/origin/)。

通过这个 refspecorigin 的分支成为远程origin 的远程跟踪分支。分支名称变为远程跟踪分支名称,其中包含远程名称,在本例中为 origin。 refspec 前面的加号 + 设置“强制”标志,即,您的远程跟踪分支将被更新以匹配远程的分支名称,无论它需要什么来匹配。 (如果没有+,分支更新仅限于“快进”更改,并且标签更新从 Git 版本 1.8.2 左右开始被忽略——在此之前应用相同的快进规则。)

标签

但是标签呢?它们没有参考规范——至少,默认情况下没有。您可以设置一个,在这种情况下,refspec 的形式取决于您;或者你可以运行git fetch --tags。使用 --tags 具有将 refs/tags/*:refs/tags/* 添加到 refspec 的效果,即,它会带来所有标签(但不会更新 your 标签,如果您已经有一个具有该名称的标签, 不管遥控器的标签是什么 编辑,2017 年 1 月:从 Git 2.10 开始,测试表明 --tags 会从遥控器的标签中强制更新您的标签,就好像 refspec 读取了 @987654372 @; 这可能与早期版本的 Git 的行为有所不同)。

注意这里没有重命名:如果远程origin 有标签xyzzy,而你没有,而你git fetch origin "refs/tags/*:refs/tags/*",你得到refs/tags/xyzzy 添加到你的存储库(指向相同的提交在遥控器上)。如果您使用+refs/tags/*:refs/tags/*,那么您的标签xyzzy(如果有的话)将被origin 中的标签替换。也就是说,refspec 上的 + force 标志意味着“用我的 Git 从他们的 Git 获得的值替换我的引用值”。

获取期间的自动标记

由于历史原因,3如果您既不使用--tags 选项也不使用--no-tags 选项,git fetch 将采取特殊措施。请记住,我们在上面说过,无论您的本地 Git 是否想要查看它们,远程都会首先向您的本地 Git 显示其所有引用。4 您的 Git 会记下它此时看到的所有标签。 然后,当它开始下载任何它需要处理它正在获取的任何提交对象时,如果其中一个提交与任何这些标签具有相同的 ID,git 将添加该标签 - 或那些标签,如果多个标签有ID - 到您的存储库。

编辑,2017 年 1 月:测试表明 Git 2.10 中的行为现在是:如果他们的 Git 提供了一个名为 Tand 的标签,那么你没有一个名为TT 关联的提交 ID 是您的 git fetch 正在检查的其分支之一的祖先,您的 Git 添加 T 到您的标签,无论有无--tags。添加--tags 会导致您的Git 获取所有他们的标签,并强制更新。

底线

您可能必须使用git fetch --tags 来获取他们的标签。如果他们的标签名称与您现有的标签名称冲突,您可能(取决于 Git 版本)甚至必须删除(或重命名)您的一些标签,然后运行 ​​git fetch --tags,以获取他们的标签.由于标签(与远程分支不同)没有自动重命名功能,因此您的标签名称必须与其标签名称匹配,这就是您可能会遇到冲突问题的原因。

大多数正常情况下,一个简单的git fetch 将完成这项工作,带来他们的提交和他们的匹配标签,因为他们——无论他们是谁——都会在当时标记提交他们发布这些提交,您将跟上他们的标签。如果您不制作自己的标签,也不混合它们的存储库和其他存储库(通过多个遥控器),您也不会有任何标签名称冲突,因此您不必大惊小怪地删除或重命名标签以获取他们的标签。

当您需要限定名称时

我在上面提到过,refs/ 几乎总是可以省略,refs/heads/refs/tags/ 等大部分时间都可以省略。但是当不能你呢?

完整(或几乎完整)的答案在the gitrevisions documentation 中。 Git 将使用链接中给出的六步序列将名称解析为提交 ID。奇怪的是,标签会覆盖分支:如果有标签xyzzy 和分支xyzzy,并且它们指向不同的提交,那么:

git rev-parse xyzzy

会给你标签指向的ID。然而——这正是gitrevisions 所缺少的——git checkout 更喜欢分支名称,所以git checkout xyzzy 会将你放在分支上,而忽略标签。

如果有歧义,您几乎总是可以使用其全名refs/heads/xyzzyrefs/tags/xyzzy 拼出引用名称。 (请注意,这确实适用于git checkout,但可能以一种意想不到的方式:git checkout refs/heads/xyzzy 导致分离头检出而不是分支检出。这就是为什么你只需要注意@ 987654404@ 将首先使用短名称作为分支名称:即使标签 xyzzy 存在,这也是您签出分支 xyzzy 的方式。如果要签出标签,可以使用 refs/tags/xyzzy。)

因为(如gitrevisions 注释)Git 会尝试refs/<em>name</em>,您也可以简单地写tags/xyzzy 来识别标记为xyzzy 的提交。 (如果有人设法将名为xyzzy 的有效引用写入$GIT_DIR,则这将解析为$GIT_DIR/xyzzy。但通常只有各种*HEAD 名称应该在$GIT_DIR 中。)


1好吧,好吧,“不是只是学究”。 :-)

2有些人会说“非常没有帮助”,实际上我倾向于同意。

3基本上,git fetch 以及远程和 refspecs 的整个概念,是在 Git 1.5 左右出现的较晚添加到 Git 的。在此之前,只有一些特殊的特殊情况,标签获取就是其中之一,所以它通过特殊代码被继承了。

4如果有帮助,请将远程 Git 想象成 flasher,这是俚语的意思。

【讨论】:

  • 很棒的文章。一个小笨蛋:git fetch 只会在给定 --tags arg 的情况下获取遥控器的标签。
  • @cweekly:--tags--no-tags 和 default 的行为实际上相当棘手。默认设置是引入在您引入的提交中没有的标签。(请参阅 2017 年 1 月的编辑。)但是这里也有小故障,现代 Git 有它的 --tags/ --no-tags 处理代码再次修改,这可能会导致更多特殊的极端情况。
【解决方案3】:

要获取特定的标记代码,请尝试创建一个新分支,添加获取其中的标记代码。 我已经通过命令完成了:$git checkout -b newBranchName tagName

【讨论】:

    【解决方案4】:

    为了检查一个 git 标签,你可以执行以下命令

    git checkout tags/tag-name -b branch-name
    

    如下所述。

     git checkout tags/v1.0 -b v1.0-branch
    

    要获取所有标签,请使用命令

    git fetch --all --tags
    

    【讨论】:

    • +1 虽然不如上述答案全面,但由于其简单性,我投了赞成票。喜欢上面的细节,但有时我需要的只是简单的东西:D
    【解决方案5】:

    这有点断章取义,但如果你在这里是因为你想像我一样标记一个特定的提交

    这是执行此操作的命令:-

    例子:

    git tag -a v1.0 7cceb02 -m "Your message here"
    

    7cceb02 是提交 ID 的开始部分。

    然后您可以使用git push origin v1.0 推送标签。

    您可以使用git log 来显示当前分支中的所有提交 ID。

    【讨论】:

      【解决方案6】:

      当我想要一个标签时,通常是获取或构建一个稳定的版本。

      换句话说,我不想要一个新的分支。我只想将标签提交到它所在的实际分支上。我不会改变任何东西。当我完成它时,我可能想立即回到分支的 HEAD。

      简单。签出带有标签的分支,然后及时将其重置回标签:

      git reset --hard tags/1.2.3
      

      对我来说,到目前为止,99.9% 的时间都是我想要的。就给我吧。完成后,我将通过简单的git pull 尽快恢复。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-03
        • 2011-05-10
        • 2021-11-11
        • 1970-01-01
        • 2010-11-07
        相关资源
        最近更新 更多