Push git commits & tags simultaneously
Asked Answered
R

6

585

git push --tags is a separate operation to git push since pushing tags should be a conscious choice to avoid accidentally pushing the wrong one. That's fine. But how do I push them both simultaneously / atomically? (git push && git push --tags is not perfectly atomic.)

Regorge answered 19/9, 2010 at 9:21 Comment(10)
What's your problem with git push && git push --tags?Mabuse
Nothing in particular, it's just slower since the connection has to be established twice.Regorge
See my updated answer below: there is a new --follow-tags option since git 1.8.3Waterbuck
Another reason not to do these separately, is to avoid triggering two CI builds for the same commit, when you have that kind of automation in place.Stationer
also --tags does not distinguish between lightweight and annotated tags sourceRossiya
@Mabuse git push && git push --tags will trigger the CI pipeline twice, although this may have been irrelevant 10 years ago.Glissade
If all you care about is not triggering CICD twice, try git push -o ci.skip && git push --tagsNettles
@Nettles — I hadn't heard about push options before. That's neat, but I think your command only works when using Gitlab?Regorge
@Nettles I'll vote that up if you make it a real answer. It's kind of a niche answer, but there are a lot of people using gitlab.Manthei
🌟 Some CI tools determine if it's occurring a release or a pre-release by checking contextually that both commit and tag pushLacroix
W
797

Update August 2020

As mentioned originally in this answer by SoBeRich, and in my own answer, as of git 2.4.x

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

(Note: this actually work with HTTPS only with Git 2.24)

Update May 2015

As of git 2.4.1, you can do

git config --global push.followTags true

If set to true enable --follow-tags option by default.
You may override this configuration at time of push by specifying --no-follow-tags.

As noted in this thread by Matt Rogers answering Wes Hurd:

--follow-tags only pushes annotated tags.

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

That would be pushed (as opposed to git tag <tagname>, a lightweight tag, which would not be pushed, as I mentioned here)

Update April 2013

Since git 1.8.3 (April 22d, 2013), you no longer have to do 2 commands to push branches, and then to push tags:

The new "--follow-tags" option tells "git push" to push relevant annotated tags when pushing branches out.

You can now try, when pushing new commits:

git push --follow-tags

That won't push all the local tags though, only the one referenced by commits which are pushed with the git push.

Git 2.4.1+ (Q2 2015) will introduce the option push.followTags: see "How to make “git push” include tags within a branch?".

Original answer, September 2010

The nuclear option would be git push --mirror, which will push all refs under refs/.

You can also push just one tag with your current branch commit:

git push origin : v1.0.0 

You can combine the --tags option with a refspec like:

git push origin --tags :

(since --tags means: All refs under refs/tags are pushed, in addition to refspecs explicitly listed on the command line)


You also have this entry "Pushing branches and tags with a single "git push" invocation"

A handy tip was just posted to the Git mailing list by Zoltán Füzesi:

I use .git/config to solve this:

[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

Beware, as commented by Aseem Kishore

push = +refs/heads/* will force-pushes all your branches.

This bit me just now, so FYI.


René Scheibe adds this interesting comment:

The --follow-tags parameter is misleading as only tags under .git/refs/tags are considered.
If git gc is run, tags are moved from .git/refs/tags to .git/packed-refs. Afterwards git push --follow-tags ... does not work as expected anymore.

Waterbuck answered 19/9, 2010 at 10:0 Comment(34)
Thanks for the detailed answer. I'm afraid git push --tags : doesn't work for me, but git push origin --tags : did. Not sure if that's a configuration thing on my end or a typo on yours.Regorge
@Will: more a typo on my side. I have fixed it in my answer.Waterbuck
The one comment on the post you link to correctly points out that the push = +refs/heads/* line force-pushes all your branches. This bit me just now, so FYI.Hacienda
Re: the --follow-tags flag added in git 1.8.3, can I configure my git installation to make that the default?Anchoveta
@TrevorBurnham no, only the value of push.default (git-scm.com/docs/git-config) can define default actions on push (nothing, matching, upstream, simple as in https://mcmap.net/q/13083/-difference-between-git-checkout-track-origin-branch-and-git-checkout-b-branch-origin-branch). You need to add --follow-tag explicitly.Waterbuck
@Waterbuck What if I want to force push the tag? git push --follow-tags -f didn't work for me.Nonprofit
@user640378 not that I know of. I would force push a tag first, then do a classic git push --follow-tagsWaterbuck
@MikeCampbellWhe it comes to tags (git-scm.com/book/en/Git-Basics-Tagging#Creating-Tags), I suspect this is to favor pushing annotated tags instead of lightweight ones.Waterbuck
It should be noted that if you have set push.default=simple in your git config, then git push --follow-tags doesn't work. In that case you still have to use git push && git push --tags.Foster
@Foster strange... you can find scripts out there (like github.com/davidheryanto/etc/blob/master/git.txt) which do set push.default to simple, and to a push --follow-tags. The tags on the (single) branch you are pushing should be take into account.Waterbuck
@Waterbuck A coworker of mine just had that problem. Only after setting push.default to matching he could use git push --follow-tags. Before that it didn't work. The git version of him is 1.8.5.2.Foster
@Foster it would be interesting to see if that persists with a more recent git 2.1+ version.Waterbuck
@TrevorBurnham You can always create an alias shortcut in .profile or .bash_profile. alias gpush='git push --follow-tags' or alias gpush='git push && git push --tags' would allow you just run gpush at the command line to trigger whatever flavor push you want.Sandie
--follow-tags doesn't work with git 2.1.0. I have push.default=simple, which is the default.Zoophilia
@Zoophilia Do you have an error message? Because that option is still in the newly released Git 2.3.5 (github.com/git/git/blob/…)Waterbuck
@Zoophilia if the tags are already pushed, it wouldn't push them again.Waterbuck
@Waterbuck they are not. Typical scenario I create a commit, I tag it, I do git push --follow-tags. Commit is pushed, tag is not.Zoophilia
@Zoophilia then your tag is not an annotated tag, but a lightweight one. If it was annotated, it would be pushed as well.Waterbuck
Let us continue this discussion in chat.Zoophilia
Remove the '+' if you don't want to force-push by default. (Hint: unless your remote repository really is supposed to mirror everything you do, yo do not.)Grissel
Could I do the same thing with git pull?Ivaivah
[remote "origin"] url can only specify one repository? could it for all repositories. @VoncAlyosha
@Alyosha see https://mcmap.net/q/13089/-how-can-i-pull-push-from-multiple-remote-locations for multiple urls per remote.Waterbuck
@Vonc only skip url attribute, fetch & push are OK for tags.Alyosha
Why isn't follow-tags the default? Are there any cases where you want to push changes but not tags?Hemialgia
@Hemialgia yes, by default, Git does not presume that you want to push tags: you might have produced hundreds of them by mistake, or only one, for internel usage. Yet, with git config --global push.followTags true, you can make it the default for your repos.Waterbuck
@Waterbuck : those cases seem quite contrived. I think for most users, the pricinple of least surpise implies that tags should be pushed by default.Hemialgia
@Hemialgia I agree. I suspect this is mostly for historic reason. Again, for now, a global setting enable you to make that permanent, but yes, this is not the default yet.Waterbuck
The --follow-tags parameter is misleading as only tags under .git/refs/tags are considered. If git gc is run, tags are moved from .git/refs/tags to .git/packed-refs. Afterwards git push --follow-tags ... does not work as expected anymore.Eurhythmic
@RenéScheibe Interesting. I have included your comment in the answer for more visibility.Waterbuck
Your link to "git 2.4.x" links to git-config, is that intentional?Wigwag
@Wigwag That seems an error indeed. I have restore the proper link.Waterbuck
So does René Scheibe's "interesting comment" (as noted in the answer) mean that git push will stop pushing tags related to commits if git gc has been run? Doesn't that mean --follow-tags is partially broken, if it sometimes doesn't do its job based upon the history of the repository? (It's like git commit will make a commit, but not if you used to have a branch named foo and then deleted it.) Isn't that bug-filing-worthy? Or am misinterpreting the comment?Turf
@GarretWilson I haven't experienced that issue. And I don't see it discussed on the Git mailing list.Waterbuck
M
25

Since Git 2.4:

git push --atomic origin <branch name> <tag>
Macedonian answered 8/9, 2019 at 14:38 Comment(5)
lol, I think I'd rather git push; git push --tagsKynan
@BlaineLafreniere lol, it’s not “simultaneous” and defies the questionMacedonian
why would you type all that out, when you could type something shorter, and achieve the same result?Kynan
Not the same. Atomicity. There are a couple of articles on WikipediaMacedonian
Nope, this still triggers github workflows twice.Favata
S
13

Let's say you have created a new repo on github. So the first step would be to clone the repo:git clone {Your Repo URL}

You do your work, add some files, code etc., then push your changes with:

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

Now our changes are in main branch. Let's create a tag:

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

If you want to delete the tag:

git tag --delete v1.0.0           # deletes tag locally    
git push --delete origin v1.0.0   # deletes remote tag
Secularity answered 27/4, 2019 at 16:56 Comment(5)
I tried your solution with git-2.21.0.windows.1 and found that 3 only pushes tagCinereous
I used "git commit -m "msg" in step 1 and there was no -a parameter. This could be why. Thank you for the followup!Cinereous
@RajeshGupta it does NOT push to remote. Just locally to origin. Run git status after your three commands and you will see something like "your branch is ahead of 'origin/develop' by 1 commit. (use "git push" to publish your local commits)"Adai
@RajeshGupta actually what you suggested works (sorry for my last comment). But you have a little typo in step 3. It should be git push origin 0.1.0 - you should omit the word 'tag'. Then it works really good. And for me even better than the --follow-tags option.Adai
However I found another issue with this approach. I wondered why I can't see any related commit on develop branch. Then I noticed in Github UI --> "This commit does not belong to any branch on this repository." This is strange. Any idea whats going wrong?Adai
B
7

Just tested on git 2.31.0: git push <refspec> --tags. This has the advantage that it pushes ALL tags, not just annotated tags like --follow-tags.

Balaklava answered 18/3, 2021 at 23:3 Comment(1)
This works! This needs to explicitly name both the remote and the branch name but at least it pushes all the work in a single shotBrachy
R
5

To avoid triggering two CI builds for the same commit on Gitlab:

git push -o ci.skip && git push --tags

As suggested by @user1160006 here.

Roseannroseanna answered 15/3, 2022 at 11:58 Comment(3)
On gitlab it shows a pipeline, its just in the skipped state (which breaks pipeline badges). So it saves build ressources, but it doesn't allow to have a clean view of the pipeline's state.Eri
Thankfully (at least in this context) I don't use pipeline badges, while on the other side I'm quite sensible to resorce usage, and even more to the time required to complete the pipeline actions, expecially if the second push triggers a deployment and I'm waiting for it's completion for a final "overall" test. However @Eri let me ask: while the first push sets the pileline to a skipped state, the second one which follow immediatly should restore the normal state, so it's just a temporary glitchRoseannroseanna
I would say the same, but for some reason badges are not taking the 2nd pipeline into account. Even when the 2nd pipeline succeed the badge shows the "unknown" tag (that I guess correspond to the skipped pipeline, or maybe its just because the commit triggered two pipelines).Eri
G
0

Git GUI

Git GUI has a PUSH button - pardon the pun, and the dialog box it opens has a checkbox for tags.

I pushed a branch from the command line, without tags, and then tried again pushing the branch using the --follow-tags option descibed above. The option is described as following annotated tags. My tags were simple tags.

I'd fixed something, tagged the commit with the fix in, (so colleagues can cherry pick the fix,) then changed the software version number and tagged the release I created (so colleagues can clone that release).

Git returned saying everything was up-to-date. It did not send the tags! Perhaps because the tags weren't annotated. Perhaps because there was nothing new on the branch.

When I did a similar push with Git GUI, the tags were sent.

Tags sent with Git GUI

For the time being, I am going to be pushing my changes to my remotes with Git GUI and not with the command line and --follow-tags.

Greenish answered 2/7, 2019 at 16:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.