什么是 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
What is git tag, How to create tags & How to checkout git remote tag(s)
提问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 中的标签是什么
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 等)。尽管标记可能看起来类似于分支,但是标记不会改变。它直接指向历史记录中的特定提交。
You will not be able to checkout the tags if it's not locally in your repository so first, you have to fetch
the 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 origin
use 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.
以上所有内容都会做同样的事情,因为标签只是一个指向给定提交的指针。
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 中一样添加元数据:
姓名、电子邮件、日期、评论和签名
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 checkout
command. As explained above tags are like any other commits so we can use checkout
and 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 --branch
to 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=
--branch
can 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/tags
instead of just specifying the <tagname>
.
使用refs/tags
而不只是指定<tagname>
.
Why?
- It's recommended to use refs/tags
since 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-tags
pushes 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)
- 带注释的标签(因此您可以跳过本地/临时构建标签)
- 当前分支(位于历史记录上)的可访问标签(祖先)
From Git 2.4 you can set it using configuration
从 Git 2.4 开始,您可以使用配置进行设置
$ git config --global push.followTags true
回答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/stash
is 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_HEAD
in particular are all also names that may refer to specific commits (though HEAD
normally contains the name of a branch, i.e., contains ref: refs/heads/branch
). But in general, references start with refs/
.
有迹象表明,不开始一些不寻常的特殊情况名称refs/
:HEAD
,ORIG_HEAD
,MERGE_HEAD
,和CHERRY_PICK_HEAD
特别皆是也可能是指特定的提交(虽然名字HEAD
通常包含分支的名称,即包含)。但一般来说,引用以.ref: refs/heads/branch
refs/
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 fetch
and push
operations. You can also use git ls-remote
or git remote show
to see them, but fetch
and push
are the more interesting points of contact.
确实,引用不仅存在于您自己的存储库中,还存在于远程存储库中。然而,Git会为您提供了仅在非常特定的时间访问远程仓库的引用:即,在fetch
和push
操作。您也可以使用git ls-remote
或git remote show
来查看它们,但是fetch
和push
是更有趣的联系点。
Refspecs
参考规格
During fetch
and 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 fetch
as 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.)
正是通过这个 refspec,origin
的分支成为您的 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 --tags
has 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 --tags
forcibly 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 origin
has tag xyzzy
, and you don't, and you git fetch origin "refs/tags/*:refs/tags/*"
, you get refs/tags/xyzzy
added 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 --tags
option nor the --no-tags
option, git fetch
takes 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 fetch
is examining, your Git adds Tto your tags with or without --tags
. Adding --tags
causes 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 --tags
to 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 fetch
will 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 gitrevisions
documentation. 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 xyzzy
and 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 gitrevisions
—git checkout
prefers branch names, so git checkout xyzzy
will 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/xyzzy
or refs/tags/xyzzy
. (Note that this doeswork with git checkout
, but in a perhaps unexpected manner: git checkout refs/heads/xyzzy
causes a detached-HEAD checkout rather than a branch checkout. This is why you just have to note that git checkout
will use the short name as a branch name first: that's how you check out the branch xyzzy
even if the tag xyzzy
exists. If you want to check out the tag, you can use refs/tags/xyzzy
.)
如果出现歧义,您几乎总是可以使用其全名refs/heads/xyzzy
或refs/tags/xyzzy
. (请注意,这确实适用于git checkout
,但以一种可能出乎意料的方式:git checkout refs/heads/xyzzy
导致分离的 HEAD 结帐而不是分支结帐。这就是为什么您只需要注意git checkout
将首先使用短名称作为分支名称:这就是您的方式xyzzy
即使标签xyzzy
存在,也要检出分支。如果要检出标签,可以使用refs/tags/xyzzy
.)
Because (as gitrevisions
notes) Git will try refs/name
, you can also simply write tags/xyzzy
to identify the commit tagged xyzzy
. (If someone has managed to write a valid reference named xyzzy
into $GIT_DIR
, however, this will resolve as $GIT_DIR/xyzzy
. But normally only the various *HEAD
names should be in $GIT_DIR
.)
因为(作为gitrevisions
注释)Git 会尝试,您也可以简单地编写以识别标记为 的提交。(但是,如果有人设法将名为into的有效引用写入,这将解析为。但通常只有各种名称应该在 中。)refs/name
tags/xyzzy
xyzzy
xyzzy
$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