本文翻译自:What is git tag, How to create tags & How to checkout git remote tag(s)
when I checkout remote git tag use command like this: 当我签出远程git标签时使用这样的命令:
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。
#1楼
参考:https://stackoom.com/question/2Qxwo/什么是git标签-如何创建标签以及如何结帐git-remote-tag-s
#2楼
Let's start by explaining what a tag in git is 让我们首先解释一下git中的标签是什么
A tag is used to label and mark a specific commit in the history. 标记用于标记和标记历史记录中的特定提交 。
It is usually used to mark release points (eg. v1.0, etc.). 它通常用于标记释放点(例如v1.0等)。Although a tag may appear similar to branch, a tag, however, does not change . 虽然标签可能看起来与分支类似,但标签不会改变 。
It points directly to a specific commit in the history. 它直接指向历史中的特定提交 。
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 checkout 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 tag is only a pointer to a given commit. 以上所有内容都是相同的,因为tag只是指向给定提交的指针。
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: 有两种方法可以创建标记:
# normal tag
git tag
# annotated tag
git tag -a
The difference between the 2 is that that the when creating an annotated tag you can add metadata like you have in a git commit: 2之间的区别在于,在创建带注释的标签时,您可以像在git commit中一样添加元数据:
name, e-mail, date, comment & signature 姓名,电子邮件,日期,评论和签名
How to delete tags? 如何删除标签?
# delete any given tag
git tag -d <tag name>
# Don't forget to remove the deleted tag form the server with push tags
How to clone specific tag? 如何克隆特定标签?
In order grab the content of a given tag you can use the checkout
command. 为了获取给定标记的内容,您可以使用checkout
命令。
As explained above tags are like any other commits so we can use checkout
and instead of using the SHA-1 simply replace it with the tag_name 如上所述,标签与任何其他提交一样,因此我们可以使用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 使用clone命令
Since git support shallow clone by adding the --branch
to the clone command we can use the tag name instead of the branch name. 由于git通过将--branch
添加到clone命令来支持浅克隆 ,因此我们可以使用标记名称而不是分支名称。 Git knows how to "translate" the given SHA-1 to the relevant commit Git知道如何将给定的SHA-1“翻译”到相关的提交
# Clone a specific tag name using git clone
git clone <url> --branch=<tag_name>
git clone --branch= git clone --branch =
--branch
can also take tags and detaches the HEAD at that commit in the resulting repository.--branch
还可以在生成的存储库中的标记处获取标记并分离HEAD。
#3楼
(This answer took a while to write, and codeWizard's answer is 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". 没有“远程Git标签”这样的东西。 There are only "tags". 只有“标签”。 I point all this out not to be pedantic, 1 but because there is a great deal of confusion about this with casual Git users, and the Git documentation is not very helpful 2 to beginners. 我点出这一切并非是迂腐,1,但因为存在混淆这个随随便便的Git用户带来了极大的交易,Git的文件是不是非常有帮助2至初学者。 (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.) (目前尚不清楚是否由于文档较差或文档较差而导致混淆,因为这本质上有点令人困惑,或者是什么。)
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/
. 特定提交的名称的一般形式--Git调用引用 - 是以refs/
开头的任何字符串。 A string that starts with refs/heads/
names a branch; 以refs/heads/
name开头的字符串; a string starting with refs/remotes/
names a remote-tracking branch; 以refs/remotes/
开头的字符串远程跟踪分支; and a string starting with refs/tags/
names a tag. 以及以refs/tags/
开头的字符串。 The name refs/stash
is the stash reference (as used by git stash
; note the lack of a trailing slash). 名称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, ie, contains ref: refs/heads/ branch
). 有一些不常见的特殊情况名称不以refs/
开头: HEAD
, ORIG_HEAD
, MERGE_HEAD
和CHERRY_PICK_HEAD
特别是也可以引用特定提交的名称(尽管HEAD
通常包含分支的名称,即包含ref: refs/heads/ branch
)。 But in general, references start with refs/
. 但一般来说,引用以refs/
开头。
One thing Git does to make this confusing is that it allows you to omit the refs/
, and often the word after refs/
. Git做的一件令人困惑的事情是,它允许你省略refs/
,通常是refs/
之后的单词。 For instance, you can omit refs/heads/
or refs/tags/
when referring to a local branch or tag—and in fact you must omit refs/heads/
when checking out a local branch! 例如,您可以在引用本地分支或标记时省略refs/heads/
或refs/tags/
- 实际上,在签出本地分支时必须省略refs/heads/
! You can do this whenever the result is unambiguous, or—as we just noted—when you must do it (for git checkout branch
). 只要结果是明确的,你就可以这样做,或者 - 正如我们刚才所说 - 当你必须这样做时(对于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. 但是,Git只允许您在非常特定的时间访问远程存储库的引用:即,在fetch
和push
操作期间。 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 ls-remote
或git remote show
来查看它们,但是fetch
和push
是更有趣的联系点。
Refspecs Refspecs
During fetch
and push
, Git uses strings it calls refspecs to transfer references between the local and remote repository. 在fetch
和push
期间,Git使用它调用refspecs的字符串来传输本地和远程存储库之间的引用。 Thus, it is at these times, and via refspecs, that two Git repositories can get into sync with each other. 因此,在这些时候,通过refspecs,两个Git存储库可以相互同步。 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
有一些特殊的魔法,它会影响分支名称和标记名称。
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. 您应该将git fetch
视为指示您的Git调用(或者可能是文本消息)另一个Git - “远程” - 并与之进行对话。 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. 在这个对话的早期,远程列出了它的所有引用: refs/heads/
所有内容以及refs/tags/
,以及它具有的任何其他引用。 Your Git scans through these and (based on the usual fetch refspec) renames their branches. 你的Git扫描这些并(基于通常的fetch refspec) 重命名它们的分支。
Let's take a look at the normal refspec for the remote named origin
: 我们来看看远程命名origin
的正常refspec:
$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$
This refspec instructs your Git to take every name matching refs/heads/*
—ie, every branch on the remote—and change its name to refs/remotes/origin/*
, ie, 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/*
-ie匹配的每个名称,遥控器上的每个分支 - 并将其名称更改为refs/remotes/origin/*
,即保持匹配的部分相同,更改分支名称( refs/heads/
)到远程跟踪分支名称( refs/remotes/
,具体来说, refs/remotes/origin/
)。
It is through this refspec that origin
's branches become your remote-tracking branches for remote origin
. 正是通过这个refspec , origin
的分支成为远程origin
远程跟踪分支。 Branch name becomes remote-tracking branch name, with the name of the remote, in this case origin
, included. 分支名称变为远程跟踪分支名称,包含远程名称(在本例中为origin
)。 The plus sign +
at the front of the refspec sets the "force" flag, ie, your remote-tracking branch will be updated to match the remote's branch name, regardless of what it takes to make it match. refspec前面的加号+
设置“强制”标志,即远程跟踪分支将更新以匹配远程的分支名称,无论使其匹配需要什么。 (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.) (如果没有+
,分支更新仅限于“快进”更改,并且自Git版本1.8.2左右之后,标签更新将被忽略,然后应用相同的快进规则。)
Tags 标签
But what about tags? 但标签怎么样? There's no refspec for them—at least, not by default. 它们没有refspec - 至少,默认情况下不是。 You can set one, in which case the form of the refspec is up to you; 您可以设置一个,在这种情况下,refspec的形式由您决定; or you can run git fetch --tags
. 或者你可以运行git fetch --tags
。 Using --tags
has the effect of adding refs/tags/*:refs/tags/*
to the refspec, ie, it brings over all tags ( but does not update your tag if you already have a tag with that name, regardless of what the remote's tag says Edit, 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). 使用--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). 请注意,这里没有重命名:如果远程origin
有标签xyzzy
,而你没有,并且你git fetch origin "refs/tags/*:refs/tags/*"
,你会得到refs/tags/xyzzy
添加到你的repository(指向与远程相同的提交)。 If you use +refs/tags/*:refs/tags/*
then your tag xyzzy
, if you have one, is replaced by the one from origin
. 如果您使用+refs/tags/*:refs/tags/*
那么您的标签xyzzy
(如果有的话)将替换为来自origin
标签。 That is, the +
force flag on a refspec means "replace my reference's value with the one my Git gets from their Git". 也就是说,refspec上的+
force标志意味着“将我的引用值替换为我的Git从Git获取的值”。
Automagic tags during fetch 获取期间的自动标记
For historical reasons, 3 if you use neither the --tags
option nor the --no-tags
option, git fetch
takes special action. 由于历史的原因,3如果您既不用--tags
选项也不是--no-tags
选项, git fetch
采取特别行动。 Remember that we said above that the remote starts by displaying to your local Git all of its references, whether your local Git wants to see them or not. 请记住,我们上面说过,远程启动时会向您的本地Git显示其所有引用,无论您的本地Git是否想要查看它们。 4 Your Git takes note of all the tags it sees at this point. 4你的Git会记录它此时看到的所有标签。 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. 然后,当它开始下载任何提交对象时,它需要处理它所提取的任何内容,如果其中一个提交具有与任何这些标记相同的ID,git将添加该标记 - 或者那些标记,如果多个标记具有该ID-to你的存储库。
Edit, Jan 2017: testing shows that the behavior in Git 2.10 is now: If their Git provides a tag named T , and you do not have a tag named T , and the commit ID associated with T is an ancestor of one of their branches that your git fetch
is examining, your Git adds T to your tags with or without --tags
. 编辑,2017年1月:测试显示Git 2.10中的行为现在是:如果他们的Git提供了一个名为T的标签, 并且您没有名为T的标签, 并且与T关联的提交ID是其中一个分支的祖先您的git fetch
正在检查,您的Git会将T添加到您的标记中,有或没有--tags
。 Adding --tags
causes your Git to obtain all their tags, and also force update. 添加--tags
会导致您的Git获取所有标记,并强制更新。
Bottom line 底线
You may have to use git fetch --tags
to get their tags. 您可能必须使用git fetch --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. 如果他们的标签名称与您现有的标签名称冲突,您可能 (取决于Git版本)甚至必须删除(或重命名)您的某些标签,然后运行git fetch --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. 由于标签(与远程分支不同)没有自动重命名,因此标签名称必须与其标签名称匹配,这就是您可能遇到冲突问题的原因。
In most normal 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. 但是,在大多数正常情况下,一个简单的git fetch
将完成这项工作,带来他们的提交和匹配的标签,因为他们 - 无论他们是谁 - 将在他们发布这些提交时标记提交,你将跟上他们的标签。 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. 如果你没有制作自己的标签,也没有混合他们的存储库和其他存储库(通过多个遥控器),你也不会有任何标签名称冲突,所以你不必为删除或重命名标签而烦恼获得他们的标签。
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. 我上面提到你可以省略refs/
几乎总是,并且在大多数时候refs/heads/
和refs/tags/
等等。 But when can't you? 但是什么时候不能 ?
The complete (or near-complete anyway) answer is in the gitrevisions
documentation . 完整的(或接近完整的)答案在gitrevisions
文档中 。 Git will resolve a name to a commit ID using the six-step sequence given in the link. Git将使用链接中给出的六步序列将名称解析为提交ID。 Curiously, tags override branches: if there is a tag xyzzy
and a branch xyzzy
, and they point to different commits, then: 奇怪的是,标签覆盖分支:如果有标签xyzzy
和分支xyzzy
,并且它们指向不同的提交,则:
git rev-parse xyzzy
will give you the ID to which the tag points. 将为您提供标签指向的ID。 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. 然而 - 这就是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
. 如果含糊不清,您几乎总能使用其全名, refs/heads/xyzzy
或refs/tags/xyzzy
拼出引用名称。 (Note that this does work 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
.) (请注意,这确实适用于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
. 因为(正如gitrevisions
所说)Git会尝试refs/ name
,你也可以简单地编写tags/xyzzy
来识别提交标记的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
.) (如果有人设法将名为xyzzy
的有效引用写入$GIT_DIR
,但是,这将解析为$GIT_DIR/xyzzy
。但通常只有各种*HEAD
名称应该在$GIT_DIR
。)
1 Okay, okay, "not just to be pedantic". 1好吧,好吧,“ 不仅仅是为了迂腐”。 :-) :-)
2 Some would say "very not-helpful", and I would tend to agree, actually. 2有些人会说“非常有帮助”,实际上我倾向于同意。
3 Basically, 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. 3基本上, git fetch
,以及遥控器和refspecs的整个概念,对于Git来说是一个迟到的补充,发生在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. 在此之前,只有一些特殊的特殊情况,而标记获取就是其中之一,所以它通过特殊代码得到了认可。
4 If it helps, think of the remote Git as a flasher , in the slang meaning. 4如果它有所帮助,可以将远程Git视为傻瓜的意思。
#4楼
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