ChatGPT解决这个技术问题 Extra ChatGPT

什么是 git 标签,如何创建标签以及如何签出 git 远程标签

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

git checkout -b local_branch_name origin/remote_tag_name

我收到这样的错误:

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

当我使用 git tag 命令时,我可以找到 remote_tag_name。


C
CodeWizard

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

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

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

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

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

如果标签不在本地存储库中,您将无法签出标签,因此首先,您必须将标签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://i.stack.imgur.com/X4lvg.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 提交中一样添加元数据:姓名、电子邮件、日期、评论和签名

https://i.stack.imgur.com/EwBtF.jpg

如何删除标签?

删除本地标签

$ 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 添加到克隆命令来支持 shallow clone,因此我们可以使用标记名称而不是分支名称。 Git 知道如何将给定的 SHA-1 “翻译”为相关的提交

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

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

如何推送标签?

git push --标签

推送所有标签:

# Push all tags
$ git push --tags 

使用 refs/tags 而不是仅仅指定

为什么?

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

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

git push --follow-tags

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

带注释的标签(因此您可以跳过本地/临时构建标签)

当前分支(位于历史记录中)的可达标签(祖先)

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

从 Git 2.4 你可以使用配置来设置它

$ git config --global push.followTags true

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


好的。 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/<tag_name> -b <branch_name> 确实需要 -b <branch_name>git checkout tags/<tag_name> 给了我一个超然的头。根据此 article about detached head,您可以通过临时创建和删除分支来避免分离头。这是一个非常陌生的工作流程。显然,我作为一个 git 用户需要习惯于创建和删除分支以获得乐趣和利润。
我会说轻量级标签而不是普通标签。在许多存储库中,带注释的标签是常态。
C
Community

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

没有“远程 Git 标签”之类的东西。只有“标签”。我指出这一切并不是为了迂腐,1 而是因为普通 Git 用户对此有很多困惑,而且 Git 文档对初学者没有太大帮助 2。 (不清楚是因为文档质量差导致混乱,还是文档质量差是因为这本质上有点令人困惑,或者是什么。)

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

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

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

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

确实,引用不仅存在于您自己的存储库中,还存在于远程存储库中。但是,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 的遥控器的正常 refspec:

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

此 refspec 指示您的 Git 获取与 refs/heads/* 匹配的每个名称 - 即远程上的每个分支 - 并将其名称更改为 refs/remotes/origin/*,即保持匹配的部分相同,将分支名称 (refs/heads/) 更改为远程跟踪分支名称(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 读取 {5 }; 这可能与早期版本的 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 获取 all 它们的标签,并强制更新。

底线

您可能必须使用 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 拼出 ref 名称。 (请注意,这确实git checkout 一起工作,但可能以一种意想不到的方式:git checkout refs/heads/xyzzy 导致分离 HEAD 结帐而不是分支结帐。这就是为什么您只需要注意 { 3} 将首先使用短名称作为分支名称:即使标签 xyzzy 存在,这也是您签出分支 xyzzy 的方式。如果要签出标签,可以使用 refs/tags/xyzzy。)

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

1好吧,好吧,“不只是迂腐”。 :-)

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

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

4如果有帮助,可以将远程 Git 视为俚语中的 flasher


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

为了签出 git 标签,您将执行以下命令

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

例如如下所述。

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

要查找远程标签:

git ls-remote --tags origin

使用给定的标签消息创建标签

git tag <tag_name> -a -m "tag message"

将单个标签推送到远程

git push origin <tag_name>

将所有标签推送到远程

git push origin --tags

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

当我想要标签上的代码时,我可能不想创建一个分支(通常,如果我要对其进行修补,我只需要一个完整的分支)。

要将分支暂时倒回到标记处的代码,请执行以下操作:

git reset --hard tags/1.2.3

我可以根据需要简单地使用它,然后在完成后返回分支的 HEAD,只需一个简单的 git pull


R
Rahul Khatri

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


o
officialrahulmandal

这有点脱离上下文,但如果你在这里是因为你想像我一样标记一个特定的提交

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

例子:

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

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

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

您可以执行 git log 以显示当前分支中的所有提交 ID。