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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35979642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 04:01:24  来源:igfitidea点击:

What is git tag, How to create tags & How to checkout git remote tag(s)

gitgit-checkoutgit-tag

提问by Ryanqy

when I checkout remote git tag use command like this:

当我结帐远程 git tag 时,请使用如下命令:

git checkout -b local_branch_name origin/remote_tag_name

I got error like this:

我得到这样的错误:

error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.

I can find remote_tag_name when I use git tag command.

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

回答by CodeWizard

Let's start by explaining what a tag in git is

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

enter image description here

在此处输入图片说明

A tag is used to label and mark a specific commitin the history.
It is usually used to mark release points (eg. v1.0, etc.).

Although a tag may appear similar to a branch, a tag, however, does not change. It points directlyto a specific commitin the history.

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

尽管标记可能看起来类似于分支,但是标记不会改变。它直接指向历史记录中的特定提交

enter image description here

在此处输入图片说明



You will not be able to checkout the tags if it's not locally in your repository so first, you have to fetchthe tags to your local repository.

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

First, make sure that the tag exists locally by doing

首先,通过执行以下操作确保标签存在于本地

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

Then check out the tag by running

然后通过运行检查标签

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

Instead of originuse the tags/prefix.

而不是origin使用tags/前缀。



In this sample you have 2 tags version 1.0 & version 1.1 you can check them out with any of the following:

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

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

All of the above will do the same since the tag is only a pointer to a given commit.

以上所有内容都会做同样的事情,因为标签只是一个指向给定提交的指针。

enter image description here
origin: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png

在此处输入图片说明
来源:https: //backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png



How to see the list of all tags?

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

# list all tags
$ git tag

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


How to create tags?

如何创建标签?

There are 2 ways to create a tag:

有两种方法可以创建标签:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

The difference between the 2 is that when creating an annotated tag you can add metadata as you have in a git commit:
name, e-mail, date, comment & signature

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

enter image description here

在此处输入图片说明

How to delete tags?

如何删除标签?

# delete any (local) given tag
$ git tag -d <tag name>

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

How to clone a specific tag?

如何克隆特定标签?

In order to grab the content of a given tag, you can use the checkoutcommand. As explained above tags are like any other commits so we can use checkoutand instead of using the SHA-1 simply replacing it with the tag_name

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

Option 1:

选项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>

Option 2:

选项 2:

Using the clone command

使用克隆命令

Since git supports shallow cloneby adding the --branchto the clone command we can use the tag name instead of the branch name. Git knows how to "translate" the given SHA-1 to the relevant commit

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

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

git clone --branch=

--branchcan also take tags and detaches the HEAD at that commit in the resulting repository.

git clone --branch=

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



How to push tags?

如何推送标签?

git push --tags

git push --tags

To push all tags:

推送所有标签:

# Push all tags
$ git push --tags 

Using the refs/tagsinstead of just specifying the <tagname>.

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

Why? - It's recommended to use refs/tagssince sometimes tags can have the same name as your branches and simple git push will push the branch instead of the tag

为什么?- 推荐使用,refs/tags因为有时标签可以与你的分支同名,简单的 git push 会推送分支而不是标签

To push annotated tags and current history chain tags use:

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

git push --follow-tags

git push --follow-tags

This flag --follow-tagspushes both commitsand only tagsthat are both:

此标志--follow-tags推送两个提交推送两者的标签

  • Annotated tags (so you can skip local/temp build tags)
  • Reachable tags (an ancestor) from the current branch (located on the history)
  • 带注释的标签(因此您可以跳过本地/临时构建标签)
  • 当前分支(位于历史记录上)的可访问标签(祖先)

enter image description here

在此处输入图片说明

From Git 2.4 you can set it using configuration

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

$ git config --global push.followTags true


Cheatsheet: enter image description here

备忘单: 在此处输入图片说明



回答by torek

(This answer took a while to write, and codeWizard's answeris correct in aim and essence, but not entirely complete, so I'll post this anyway.)

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



There is no such thing as a "remote Git tag". There are only "tags". I point all this out not to be pedantic,1but because there is a great deal of confusion about this with casual Git users, and the Git documentation is not very helpful2to beginners. (It's not clear if the confusion comes because of poor documentation, or the poor documentation comes because this is inherently somewhat confusing, or what.)

没有“远程 Git 标签”这样的东西。只有“标签”。我指出这一切并不是迂腐,1而是因为普通 Git 用户对此有很大的困惑,而且 Git 文档对初学者不是很有帮助2。(不清楚混乱是因为糟糕的文档造成的,还是糟糕的文档是因为这本质上有点混乱,或者什么。)

There are"remote branches", more properly called "remote-tracking branches", but it's worth noting that these are actually local entities. There are no remote tags, though (unless you (re)invent them). There are only local tags, so you need to get the tag locally in order to use it.

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

The general form for names for specific commits—which Git calls references—is any string starting with refs/. A string that starts with refs/heads/names a branch; a string starting with refs/remotes/names a remote-tracking branch; and a string starting with refs/tags/names a tag. The name refs/stashis the stash reference (as used by git stash; note the lack of a trailing slash).

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

There are some unusual special-case names that do not begin with refs/: HEAD, ORIG_HEAD, MERGE_HEAD, and CHERRY_PICK_HEADin particular are all also names that may refer to specific commits (though HEADnormally contains the name of a branch, i.e., contains ref: refs/heads/branch). But in general, references start with refs/.

有迹象表明,不开始一些不寻常的特殊情况名称refs/HEADORIG_HEADMERGE_HEAD,和CHERRY_PICK_HEAD特别皆是也可能是指特定的提交(虽然名字HEAD通常包含分支的名称,即包含)。但一般来说,引用以.ref: refs/heads/branchrefs/

One thing Git does to make this confusing is that it allows you to omit the refs/, and often the word after refs/. For instance, you can omit refs/heads/or refs/tags/when referring to a local branch or tag—and in fact you mustomit refs/heads/when checking out a local branch! You can do this whenever the result is unambiguous, or—as we just noted—when you must do it (for git checkout branch).

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

It's true that references exist not only in your own repository, but also in remote repositories. However, Git gives you access to a remote repository's references only at very specific times: namely, during fetchand pushoperations. You can also use git ls-remoteor git remote showto see them, but fetchand pushare the more interesting points of contact.

确实,引用不仅存在于您自己的存储库中,还存在于远程存储库中。然而,Git会为您提供了仅在非常特定的时间访问远程仓库的引用:即,在fetchpush操作。您也可以使用git ls-remotegit remote show来查看它们,但是fetchpush是更有趣的联系点。

Refspecs

参考规格

During fetchand push, Git uses strings it calls refspecsto transfer references between the local and remote repository. Thus, it is at these times, and via refspecs, that two Git repositories can get into sync with each other. Once your names are in sync, you can use the same name that someone with the remote uses. There is some special magic here on fetch, though, and it affects both branch names and tag names.

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

You should think of git fetchas directing your Git to call up (or perhaps text-message) another Git—the "remote"—and have a conversation with it. Early in this conversation, the remote lists all of its references: everything in refs/heads/and everything in refs/tags/, along with any other references it has. Your Git scans through these and (based on the usual fetch refspec) renamestheir branches.

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

Let's take a look at the normal refspec for the remote named origin:

让我们看看远程命名的正常 refspec origin

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

This refspec instructs your Git to take every name matching refs/heads/*—i.e., every branch on the remote—and change its name to refs/remotes/origin/*, i.e., keep the matched part the same, changing the branch name (refs/heads/) to a remote-tracking branch name (refs/remotes/, specifically, refs/remotes/origin/).

此 refspec 指示您的 Git 获取匹配的refs/heads/*每个名称refs/remotes/origin/*(即远程上的每个分支)并将其名称更改为,即保持匹配部分相同,将分支名称 ( refs/heads/) 更改为远程跟踪分支名称 ( refs/remotes/,特别是, refs/remotes/origin/)

It is through this refspecthat origin's branches become your remote-tracking branches for remote origin. Branch name becomes remote-tracking branch name, with the name of the remote, in this case origin, included. The plus sign +at the front of the refspec sets the "force" flag, i.e., your remote-tracking branch will be updated to match the remote's branch name, regardless of what it takes to make it match. (Without the +, branch updates are limited to "fast forward" changes, and tag updates are simply ignored since Git version 1.8.2 or so—before then the same fast-forward rules applied.)

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

Tags

标签

But what about tags? There's no refspec for them—at least, not by default. You can set one, in which case the form of the refspec is up to you; or you can run git fetch --tags. Using --tagshas the effect of adding refs/tags/*:refs/tags/*to the refspec, i.e., it brings over all tags (but does not update yourtag if you already have a tag with that name, regardless of what the remote's tag saysEdit, Jan 2017: as of Git 2.10, testing shows that --tagsforcibly updates your tags from the remote's tags, as if the refspec read +refs/tags/*:refs/tags/*; this may be a difference in behavior from an earlier version of Git).

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

Note that there is no renaming here: if remote originhas tag xyzzy, and you don't, and you git fetch origin "refs/tags/*:refs/tags/*", you get refs/tags/xyzzyadded to your repository (pointing to the same commit as on the remote). If you use +refs/tags/*:refs/tags/*then your tag xyzzy, if you have one, is replacedby the one from origin. That is, the +force flag on a refspec means "replace my reference's value with the one my Git gets from their Git".

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

Automagic tags during fetch

获取期间的自动标记

For historical reasons,3if you use neither the --tagsoption nor the --no-tagsoption, git fetchtakes special action. Remember that we said above that the remote starts by displaying to your local Git allof its references, whether your local Git wants to see them or not.4Your Git takes note of all the tags it sees at this point. Then, as it begins downloading any commit objects it needs to handle whatever it's fetching, if one of those commits has the same ID as any of those tags, git will add that tag—or those tags, if multiple tags have that ID—to your repository.

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

Edit, Jan 2017: testing shows that the behavior in Git 2.10 is now: If their Git provides a tag named T, andyou do not have a tag named T, andthe commit ID associated with Tis an ancestor of one of their branches that your git fetchis examining, your Git adds Tto your tags with or without --tags. Adding --tagscauses your Git to obtain alltheir tags, and also force update.

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

Bottom line

底线

You may have to use git fetch --tagsto get their tags. If their tag names conflict with your existing tag names, you may(depending on Git version) even have to delete (or rename) some of your tags, and then run git fetch --tags, to get their tags. Since tags—unlike remote branches—do not have automatic renaming, your tag names must match their tag names, which is why you can have issues with conflicts.

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

In mostnormal cases, though, a simple git fetchwill do the job, bringing over their commits and their matching tags, and since they—whoever they are—will tag commits at the time they publish those commits, you will keep up with their tags. If you don't make your own tags, nor mix their repository and other repositories (via multiple remotes), you won't have any tag name collisions either, so you won't have to fuss with deleting or renaming tags in order to obtain their tags.

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

When you need qualified names

当您需要限定名称时

I mentioned above that you can omit refs/almost always, and refs/heads/and refs/tags/and so on most of the time. But when can'tyou?

我上面提到的,你可以省略refs/几乎总是和refs/heads/refs/tags/等大部分的时间。但你什么时候不能

The complete (or near-complete anyway) answer is in the gitrevisionsdocumentation. Git will resolve a name to a commit ID using the six-step sequence given in the link. Curiously, tags override branches: if there is a tag xyzzyand a branch xyzzy, and they point to different commits, then:

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

git rev-parse xyzzy

will give you the ID to which the tag points. However—and this is what's missing from gitrevisionsgit checkoutprefers branch names, so git checkout xyzzywill put you on the branch, disregarding the tag.

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

In case of ambiguity, you can almost always spell out the ref name using its full name, refs/heads/xyzzyor refs/tags/xyzzy. (Note that this doeswork with git checkout, but in a perhaps unexpected manner: git checkout refs/heads/xyzzycauses a detached-HEAD checkout rather than a branch checkout. This is why you just have to note that git checkoutwill use the short name as a branch name first: that's how you check out the branch xyzzyeven if the tag xyzzyexists. If you want to check out the tag, you can use refs/tags/xyzzy.)

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

Because (as gitrevisionsnotes) Git will try refs/name, you can also simply write tags/xyzzyto identify the commit tagged xyzzy. (If someone has managed to write a valid reference named xyzzyinto $GIT_DIR, however, this will resolve as $GIT_DIR/xyzzy. But normally only the various *HEADnames should be in $GIT_DIR.)

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



1Okay, okay, "not justto be pedantic". :-)

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

2Some would say "very not-helpful", and I would tend to agree, actually.

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

3Basically, git fetch, and the whole concept of remotes and refspecs, was a bit of a late addition to Git, happening around the time of Git 1.5. Before then there were just some ad-hoc special cases, and tag-fetching was one of them, so it got grandfathered in via special code.

3基本上,git fetch遥控器和 refspecs 的整个概念是 Git 的一个后期添加,大约发生在 Git 1.5 的时候。在此之前,只有一些临时的特殊情况,标签提取就是其中之一,因此它通过特殊代码得到了继承。

4If it helps, think of the remote Git as a flasher, in the slang meaning.

4如果有帮助,将远程 Git 视为flasher,在俚语中。

回答by mani

In order to checkout a git tag , you would execute the following command

为了签出一个 git 标签,你需要执行以下命令

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

eg as mentioned below.

例如如下所述。

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

To fetch the all tags use the command

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

git fetch --all --tags

回答by Rahul Khatri

To get the specific tag code try to create a new branch add get the tag code in it. I have done it by command : $git checkout -b newBranchName tagName

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