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

当我签出远程git标签时,使用这样的命令:

git checkout -b local_branch_name origin/remote_tag_name

我有这样的错误:

错误:路径规范origin/remote_tag_name不匹配git已知的任何文件。

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

868968 次浏览

让我们先解释一下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>

而不是origin使用tags/前缀。


在此示例中,您有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

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

在此处输入图片描述

如何删除标签?

删除本地标签

$ 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:

使用clone命令

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

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

git clone

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


如何推送标签?

git push --tags

要推送所有标签:

# Push all tags
$ git push --tags

使用refs/tags而不是仅仅指定<tagname>

为啥?

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

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

git push --follow-tags

此标志--follow-tags同时推送承诺只有标签

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

在此处输入图片描述

在Git 2.4中,您可以使用配置设置它

$ git config --global push.followTags true

备忘单: 输入图片描述


(这个答案写了一段时间,代码向导的答案在目标和本质上是正确的,但不完全完整,所以我还是会发布这个。


没有所谓的“远程Git标签”。只有“标签”。我指出这一切不是为了迂腐,1而是因为普通的Git用户对此有很多困惑,Git留档对初学者没有太大帮助。(不清楚这种困惑是因为糟糕的留档,还是糟糕的留档是因为这本质上有点令人困惑,还是什么。)

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

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

有一些不寻常的特殊情况名称不以refs/开头:HEADORIG_HEADMERGE_HEAD,特别是CHERRY_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是更有趣的联络点。

RefSpecs

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

你应该把git fetch想象成指示你的Git调用(或者发送短信)另一个Git——“遥控器”——并与它进行对话。在对话的早期,遥控器列出了它的所有引用:refs/heads/中的所有内容和refs/tags/中的所有内容,以及它拥有的任何其他引用。你的Git会扫描这些引用,并(基于通常的获取引用规范)重命名它们的分支。

让我们看一下名为origin的远程的正常引用规范:

$ 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/)。

origin的分支成为远程origin的远程跟踪分支。分支名称变为远程跟踪分支名称,其中包括远程名称,在本例中为origin。refspec前面的加号+设置“force”标志,即您的远程跟踪分支将被更新以匹配远程的分支名称,无论需要什么才能使其匹配。(如果没有+,分支更新仅限于“快进”更改,并且从Git版本1.8.2左右开始简单地忽略标记更新-在此之前应用相同的快进规则。)

标签

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

请注意,这里没有重命名:如果远程origin有标签xyzzy,而你没有,而你有git fetch origin "refs/tags/*:refs/tags/*",你会得到refs/tags/xyzzy添加到你的存储库(指向与远程相同的提交)。如果你使用+refs/tags/*:refs/tags/*,那么你的标签xyzzy,如果你有一个,是取代origin。也就是说,refspec上的+强制标志意味着“用我的Git从他们的Git获得的值替换我的引用的值”。

获取过程中的自动标签

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

编辑,2017年1月:测试显示Git 2.10中的行为现在是:如果他们的Git提供了一个名为T的标签,你没有一个名为T的标签,T关联的提交ID是git fetch正在检查的它们的一个分支的祖先,你的Git将T添加到你的标签中,有或没有--tags。添加--tags会导致你的Git获得所有他们的标签,并强制更新。

底线是

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

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

当你需要合格的名字

我上面提到,你几乎总是可以省略refs/,大多数时候可以省略refs/heads/refs/tags/等等。但是什么时候不能你呢?

完整(或接近完整)的答案在gitrevisions留档中。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导致分离HEAD签出而不是分支签出。这就是为什么您只需注意git checkout将首先使用短名称作为分支名称:即使标签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视为俚语中的闪光器

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

为了检出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

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

这里有一个命令来做到这一点:-

示例:

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

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

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

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

当我想要标记代码时,我可能不想创建一个分支(通常,如果我要热修复它,我只需要一个完整的分支)。

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

git reset --hard tags/1.2.3

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