同时推送git提交和标签

579

git push --tags 是一个独立的操作,与 git push 不同,因为推送标签应该是一个有意识的选择,以避免意外推送错误的标签。这很好。但是我如何同时 / 原子地推送它们?(git push && git push --tags 不是完全原子的。)


8
你对 git push && git push --tags 有什么问题? - fuz
30
没有特别的原因,只是因为需要建立两次连接,所以速度会变慢。 - Will Robertson
23
请看下面我更新过的回答:自 Git 1.8.3 版本以来,有一个新的 --follow-tags 选项。 - VonC
76
不把它们分开做的另一个原因是为了避免在你有这样的自动化设置时,触发同一次提交的两个CI构建。 - Alex R
13
即使这在10年前可能并不重要,但是“git push && git push --tags”操作会触发CI流水线两次。 - LLlAMnYP
显示剩余5条评论
6个回答

780

2020年8月更新

正如this答案中SoBeRich所提到的,以及我自己的回答中提到的,从git 2.4.x开始

git push --atomic origin <branch name> <tag>

注意:这实际上只适用于Git 2.24及以上的HTTPS

更新于2015年5月

截至Git 2.4.1,您可以执行以下操作:

git config --global push.followTags true

如果设置为true,则默认启用--follow-tags选项。
您可以在推送时通过指定--no-follow-tags来覆盖此配置。

正如Matt Rogers在回答Wes Hurd的这个帖子中所指出的那样

--follow-tags 仅推送带注释的标签

git tag -a -m "I'm an annotation" <tagname>

这将被推送(与轻量级标签git tag <tagname>相反,后者不会被推送,就像我在这里提到的

更新于2013年4月

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

新的"--follow-tags"选项告诉"git push"在推送分支时一起推送相关的注释标签

当推送新提交时,您现在可以尝试:

git push --follow-tags

那并不能推送所有本地标签,只有与使用 git push 推送的提交所引用的标签。

Git 2.4.1+ (Q2 2015) 将引入选项 push.followTags:请参见 "如何使“git push”包括分支内的标签?"。

原始答案,2010年9月

核心选项是 git push --mirror,它将推送 refs/ 下的所有引用。

您也可以推送当前分支提交的一个标签:

git push origin : v1.0.0 

你可以将--tags选项与refspec组合使用,例如:
git push origin --tags :

(因为 --tags 的意思是:所有在 refs/tags 下的引用都被推送,除了在命令行上明确列出的 refspecs

您还有这个条目 "使用单个"git push"命令推送分支和标签"

Zoltán Füzesi在Git邮件列表上发布了一个方便的提示:

我使用.git/config来解决这个问题:

[remote "origin"]
    url = ...
    fetch = +refs/heads/*:refs/remotes/origin/*
    push = +refs/heads/*
    push = +refs/tags/*

With these lines added git push origin will upload all your branches and tags. If you want to upload only some of them, you can enumerate them.

Haven't tried it myself yet, but it looks like it might be useful until some other way of pushing branches and tags at the same time is added to git push.
On the other hand, I don't mind typing:

$ git push && git push --tags

注意,正如Aseem Kishore评论的那样

push = +refs/heads/*强制推送你的所有分支

这个问题刚刚影响了我,所以提前告知一下。


René Scheibe添加了这条有趣的评论:

--follow-tags参数是误导性的,因为只考虑.git/refs/tags下的标签。
如果运行git gc,则标签会从.git/refs/tags移动到.git/packed-refs。之后git push --follow-tags ...不再按预期工作。


4
您提供的链接中的一条评论正确指出,push = +refs/heads/* 这行代码将强制推送您的所有分支。这刚刚对我造成了影响,所以提供给您参考。 - Aseem Kishore
2
关于在git 1.8.3中添加的--follow-tags标志,我能否配置我的git安装使其成为默认值? - Trevor Burnham
1
@VonC 如果我想强制推送标签怎么办?git push --follow-tags -f 对我没用。 - mauryat
1
@static_rtti 我同意。我怀疑这主要是出于历史原因。再次强调,目前全局设置可以让您永久更改此设置,但是是的,这还不是默认设置。 - VonC
1
“--follow-tags” 参数存在误导性,因为它只考虑 .git/refs/tags 下的标签。如果运行 git gc 命令,则会将标签从 .git/refs/tags 移动到 .git/packed-refs 中。之后,“git push --follow-tags…” 将不再按预期工作。 - René Scheibe
显示剩余29条评论

24
自Git 2.4版本以来:
git push --atomic origin <branch name> <tag>

14
哈哈,我想我宁愿执行 git push; git push --tags - Blaine Lafreniere
7
@BlaineLafreniere 哈哈,这不是“同时进行”的,完全回避了问题。 - SoBeRich
为什么要打那么多字,当你可以打得更短,并且达到相同的结果呢? - Blaine Lafreniere
4
不同。原子性。维基百科上有几篇文章。 - SoBeRich
4
不行,这仍然会触发 Github 工作流两次。 - Violet Giraffe

12

假设你已在GitHub上创建了一个新的仓库。第一步应该是克隆仓库:git clone {您的仓库URL}

完成您的工作后,添加一些文件、代码等,然后使用以下命令推送您的更改:

git add .
git commit -m "first commit"
git push

现在我们的更改已经合并到主分支。让我们创建一个标签:

git tag v1.0.0                    # creates tag locally     
git push origin v1.0.0            # pushes tag to remote

如果您想删除标签:

git tag --delete v1.0.0           # deletes tag locally    
git push --delete origin v1.0.0   # deletes remote tag

1
我尝试了您的解决方案,使用git-2.21.0.windows.1版本,并发现只有3个标签被推送。 - Dustin Sun
我在第一步使用了“git commit -m“msg”,但没有-a参数。这可能是原因。感谢您的跟进! - Dustin Sun
@RajeshGupta 它不会推送到远程。只是本地到源。在执行完你的三个命令后运行 git status,你会看到类似于“你的分支领先于 'origin/develop' 1 次提交。(使用 "git push" 发布你的本地提交)”这样的提示。 - Wlad
1
@RajeshGupta,实际上你建议的方法可行(抱歉我之前的评论)。但是在第三步中有一个小错误。应该是git push origin 0.1.0 - 你应该省略单词“tag”。然后它就非常好用了。对我来说,甚至比--follow-tags选项更好。 - Wlad
然而,我发现这种方法还存在另一个问题。我想知道为什么在develop分支上看不到任何相关的提交。然后我注意到在Github UI中-->“此提交不属于此存储库上的任何分支。”这很奇怪。有什么想法出了问题吗? - Wlad

6

在git 2.31.0上进行了测试:git push <refspec> --tags。这样做的好处是它会推送所有标签,而不仅仅是像--follow-tags一样的注释标签。


这可以用!但需要显式命名远程和分支名称,但至少可以将所有工作一次性推送。 - David Costa

4
为避免在 Gitlab 上对同一次提交触发两个 CI 构建:
git push -o ci.skip && git push --tags

正如@user1160006 在这里所建议的。


2
在GitLab上显示了一个流水线,它只是处于跳过状态(这会破坏流水线徽章)。因此,它节省了构建资源,但无法清晰地查看流水线的状态。 - cglacet
幸运的是(至少在这种情况下),我不使用管道徽章,但我对资源使用非常敏感,尤其是对完成管道操作所需的时间更加敏感,特别是如果第二次推送触发了部署,并且我正在等待它完成以进行最终的“整体”测试。 然而,@cglacet让我问一下:虽然第一次推送将管道设置为跳过状态,但紧随其后的第二次推送应该恢复正常状态,所以这只是一个暂时的故障。 - Mario Orlandi
幸运的是(至少在这种情况下),我不使用管道徽章,但我对资源使用非常敏感,对完成管道操作所需的时间更加敏感,尤其是如果第二次推送触发了部署,我正在等待它完成以进行最终的“整体”测试。 然而,@cglacet让我问一下:第一次推送将管道设置为跳过状态,紧随其后的第二次推送应该恢复正常状态,所以这只是一个暂时的故障。 - undefined
我会说同样的话,但由于某种原因徽章没有考虑第二个流水线。即使第二个流水线成功,徽章仍显示为“未知”标记(我猜这对应于被跳过的流水线,或者可能只是因为提交触发了两个流水线)。 - cglacet

0

Git GUI

Git GUI有一个PUSH按钮 - 请原谅双关语,它打开的对话框中有一个标签复选框。

我在命令行上推送了一个分支,没有标签,然后尝试使用上面描述的--follow-tags选项再次推送该分支。该选项被描述为跟随注释标签。我的标签是简单标签。

我修复了一些东西,用修复的提交打了标签(这样同事就可以挑选修复),然后更改了软件版本号并打了我创建的发布标签(这样同事就可以克隆该发布)。

Git返回说一切都是最新的。它没有发送标签!也许是因为标签没有被注释。也许是因为分支上没有新内容。

当我使用Git GUI进行类似的推送时,标签被发送了。

Tags sent with Git GUI

目前,我将使用Git GUI而不是命令行和--follow-tags来推送我的更改到我的远程。


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