Git标签也会被推送吗?

232

自从我创建了我的仓库以来,似乎我创建的标签没有被推送到仓库。当我在本地目录中执行git tag命令时,所有标签都存在,但是当我登录到远程仓库并执行git tag命令时,只有前几个标签出现。

可能的问题是什么?


3
现在可以使用git push --follow-tags,请参见我下面的回答 - VonC
2
可能是重复的问题:如何使用Git将标签推送到远程存储库? - user456814
1
同意重复问题:虽然这个较老,但另一个问题提出得更好。 - Ciro Santilli OurBigBook.com
5个回答

295
你可以这样做:
git push --tags

31
我相信这意味着 HEAD 引用不会被推送,这意味着你只推送标签。 - Dan Rosenstark
62
我建议不要使用或训练他人使用 git push --tags,因为当你的同事被训练成推送所有标签时,要摆脱错误的标签可能非常困难,因为每次想要推送新标签时,人们会继续推送其本地的旧标签。因此,我现在只会建议某人使用 git push origin <tag_name> - reducing activity
1
我认为另一个答案,https://dev59.com/DnA75IYBdhLWcg3w_uqD#16164809 应该被接受。即使不被接受,它也绝对值得一读 - 它提供了正反两方面的观点,并最终给出了更实用和正确的答案。 - Ruben Bartelink

161

在默认的git远程配置中,您必须显式地推送标签(尽管它们与其指向的提交一起被自动获取)。 您需要使用

$ git push <remote> tag <tagname>

推送单个标签,或者

$ git push <remote> --tags

要推送所有标签(或使用git push --tags将其推送到默认远程,通常为origin)。

这是非常有意的行为,使推送标签变得明确。推送标签应该是一个有意识的选择。


总结一下Junio C. Hamano 写道(由@Andre Miras在评论中提供链接):

当获取时,您正在与某人发布的远程存储库进行交互,这意味着:

  1. 存在于那里的标签集是发布者想让大家看到的所有内容,并且
  2. 不仅是您,其他人也将看到相同的标签。

换句话说,从您获取的存储库中的标签旨在成为公共和共享的。如果每个人都可以轻松地获取这些相同的标记,它将促进开发人员之间的交流。

这就是为什么 git fetch 自动“跟随”标签,即在下载它们指向的修订版本时下载标签 - 换句话说,下载所有相关的已发布标签。

当推送时,您正在从您的工作存储库推送,这大多数时间不是公共的,该存储库内的标签不是公共设计的。您可以使用自己的本地标签来标记自己的进度,因此盲目地将存储库中的所有标签推送到要推送到的存储库中以发布更改并没有意义,因为它的标签根据定义是公共的。

这就是为什么您需要显式推送标签,以将标签标记为公共。


或者,您可以配置要推送到的远程仓库始终推送所有标签,例如,在您的.git/config中放置以下内容:

[remote "publish"] # 或其他命名
    url = ...
    push = +refs/heads/*:refs/heads/*
    push = +refs/tags/*:refs/tags/*

这意味着强制推送所有头(所有分支)和所有标签(如果您不想强制推送头,请从refspec中删除“+”前缀)。


21
这是故意设计的行为,目的是让推送标签变得明确。推送标签通常应该是有意识的选择。 自动推送标签可能会带来一些问题,例如可能会在不知情的情况下覆盖已存在的标签,或者在不同的副本之间产生混淆。因此,Git默认需要显式地执行标签推送操作,以确保开发人员有意识地进行这项操作。 - Ryan Lundy
13
@Kyralessa,在这篇文章 http://git.661346.n2.nabble.com/rfd-auto-following-tags-upon-quot-git-push-quot-td6450398.html 中,Git 的现任维护者 Junio C Hamano 解释了自动推送标签的坏处。 - Andre Miras
@AndreMiras,感谢您提供这个很棒的链接。如果我们能将Junio的帖子集成到这个答案中会很好。 - Homer6
我已经寻找这个答案多年了。我总是想要推送所有的标签和引用,这告诉了我如何做,谢谢! - Seiyria
@O'Rooney:你可能想要使用一个临时和私有标签来标记一个功能在项目历史中被引入的位置(这样就不必记住对象 ID),但是这个标签只是暂时帮助你重构代码,而不是广泛发布。 - Jakub Narębski
显示剩余4条评论

97

请注意,自git 1.8.3(2013年4月22日)以来,您不再需要执行两个命令来推送分支和标签:

新的"--follow-tags"选项告诉"git push"在推出分支时同时推出相关的已注释标签

现在,在推送新提交时,您可以尝试使用该选项:

git push --follow-tags

这样做并不能推送所有本地标签,只有与使用git push推送的提交引用的已注释标签才会被推送。


这是由Junio C Hamano(gitster)commit c2aba15中引入的新功能:
新选项“--follow-tags”告诉“git push”推送缺失的已注释标签,如果它们可以通过推送出的历史记录到达。例如,如果您使用“simple”,“current”或“upstream”推送,则通常只会推送导致当前HEAD提交的历史记录,而不会推送其他内容。但是,使用此选项,您还将推送可以从该提交到达的所有已注释标签到另一侧。
配置push.followTags可以默认包含--follow-tags(Git 2.4.1+,2015年第二季度)。请参见“同时推送git提交和标签”。

3
这只会推送所有已注释的标签。大多数人/项目都使用轻量级标签。因此,在大多数情况下,git push--follow-tags不会比git push更多地推送。 - Jarl
3
@Jarl,是的,我在我的回答中提到了“已注释的”。但实际上我只使用了已注释的标签,并将轻量级标签保留为纯内部使用(即从未打算被推送)。 - VonC
1
@VonC:现在也有一个配置选项,可以将其设置为默认值,就像您在这里指出的那样:https://dev59.com/lG865IYBdhLWcg3wkfgW#3745250 - krlmlr

20

我通常做的是:

[remote "publish"] # 或任何其他名称
    url = ...
    push = :
    push = +refs/tags/*:refs/tags/*

这意味着它会推送已经存在的每个分支,以及标签。它不会强制推送,并且不会推送您没有手动推送的分支。


我也可以将其放入我的用户的全局git配置中吗?如果可以,怎么做?谢谢! :) - gucki
看起来你在强制使用标签,而不是分支。 - Adrian Ratnapala
好的,是的和不是的,我写了这个,它会推送新的标签,但不会强制推送它们,并且不会推送你还没有推送过的分支。 - mat
我尝试了Jakub的建议,但它正在推送我只想要本地的分支。这个建议mat非常完美。它同步标签,但不会同步分支,除非它们是远程跟踪分支(即它不会将新分支推送到远程,但如果它们已经在远程中,则会更新它们)。注意:如果您有一个名称相同的标签和分支,则会出现“匹配多个”错误。请参阅lostechies.com/jasonmeridth/2010/02/27/refspec-matches-more-than-one/ - josephdpurcell

6

如果你想强制获取所有标签,你可以在配置中设置:

git config remote.origin.tagopt --tags

文档中的描述:

将该值设置为--no-tags时,在从远程获取内容时禁用自动标签跟随。将其设置为--tags将从远程获取所有标签,即使它们无法从远程分支头访问。直接将这些标志传递给git-fetch(1)可以覆盖此设置。请参阅git-fetch(1)的选项--tags和--no-tags。


1
问题更偏向于“推送”方向,您的答案是否也适用于向远程推送? - a1an

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接