how to 'push --tags' ignoring some?

Viewed 614

I'd like to push all tags except a couple which are not needed. Is it possible do it without deleting them first?

The scenario: an automated release system assigns a release tag to the latest commit of the master branch, say V3.1. It also moves the 'LATEST' tag to the same new commit. (in reality there are more unique and non-unique tags created).

So, i'd like to do push --tags but ignore the 'LATEST'. Any idea how to do it?

4 Answers

If I understood correctly, I see two ways to do what you need :

  1. push only the tag your job just created, e.g : store the tag name in some $tag variable, and run :

    git push origin $tag
    
  2. you want to push more than one tag, and tags created by the job will all follow the same pattern : V3.1, V3.2 etc ...
    in that case, use a refspec which matches only those tags :

    git push origin "refs/tags/V*:refs/tags/V*"
    

See the refspec section of git help push

Git tags aren't designed to be moved, and the manual describes this.

Git supports two types of tags: lightweight and annotated.

A lightweight tag is very much like a branch that doesn’t change — it’s just a pointer to a specific commit.

Annotated tags, however, are stored as full objects in the Git database. They’re checksummed; contain the tagger name, email, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG). (Source: Git Manual)

You probably want to use a branch to point to the latest commit rather than a tag. As alluded to in the excerpt quoted above, a lightweight tag is just the same as a branch except it doesn't change, and an annotated tag is a lightweight tag with some additional information attached to it. This is useful if you want to sign the tag so you can audit who created a given release, but holds no benefit if you're using a tag to point to a moving target. That's what branches are for.

To change where a branch points, checkout the branch and reset --hard to the new sha. For example (assuming de39a48 is the new latest commit after the release).

git checkout latest git reset --hard de39a48

If you don't want LATEST treated like a tag, don't make it a tag. You can keep utterly arbitrary thumbs into the commit graph,

git update-ref LATEST v3.1^{}

is the simplest, though it'd be approporiate to carp at that for its inconsiderate use of a conventionally-reserved namespace (it's a completely global ref, like HEAD), so perhaps git update-ref refs/cithumbs/LATEST v3.1^{} would be better professional engineering. The ^{} is there to be sure of reaching the underlying commit (see git help revisions) in case you're using annotated (e.g. signed or commented) tags that carry the data in their own object.

Since git's branching is quite literally incredibly lightweight—as in, it's difficult to get people used to other vcs's gyrations to credit just how easy this can be—you could just use a branch:

git branch -f LATEST v3.1

which is essentially exactly equivalent to

git update-ref refs/heads/LATEST v3.1^{}

(the branch command also sets up a reflog by default, which you might want and can get `update-ref to do for you for any ref, see the reflog docs).

You can try

git push --dry-run --tags LATEST^

It will push every tag until the commit before the one your tag LATEST points to.

I'm not sure whether push command's refspec accepts commit hashes, but it's a dry-run so it won't actually affect anything. Then proceed with the real thing if the output fits your expectations.

Related