Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to push all annotated tags?

How do I push all annotated tags from my local repo to the remote, without pushing lightweight tags?

I use lightweight tags locally that I don't want pushed, so git push --tags is not a solution.

I am aware of git push --follow-tags but that will only push tags that are associated with commits currently being pushed.

I need this option because my normal workflow involves pushing from time to time, but only tagging when finalizing a release, and I sometimes forget to push a tag. This problem often goes undetected for a long time and causes a bit of confusion with other developers, since we become out of sync with our tags.

Since it's complicated to list which annotated tags exist locally but not remotely, I would like to solve this problem by just pushing all local annotated tags, which will ensure that all developers' local and remote repos have the same annotated tags.

like image 605
M.M Avatar asked Oct 12 '25 12:10

M.M


2 Answers

It's not too difficult. First find all annotated tags (by rejecting tags that point directly to commits rather than to annotated tag objects). This is a bit long, so you might wish to write it as a shell function:

list_annotated_tags() {
    git for-each-ref --format '%(objecttype) %(refname)' refs/tags |
        while read reftype refname; do
            case $reftype in tag) echo $refname;; esac
        done
}

Read the output of the above and use them as refspec arguments to a git push command:

git push origin $(list_annotated_tags)

and your script is complete.

like image 173
torek Avatar answered Oct 15 '25 14:10

torek


I noticed that my lightweight tags don't include a taggerdate. In that case, this will work at the command line or in a script:

taglist=`git for-each-ref refs/tags --format '%(refname:short) %09 %(taggerdate:short)' | \
grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}' | \
cut -f 1 | \
tr '\n' ' '`

followed by:

git push origin $taglist

Command summary, for anyone who is interested:

  • 1st line - retrieves a git for-each-ref tag list, formatted to show the tagname, a tab, and the date. (Only annotated tags will have a date.)
  • 2nd line - grep command searches through the 1st command's results, pulling only those tags with dates.
  • 3rd line - cut command removes everything after the initial column (ie, from before the tab following each tagname to the newline ending each result line).
  • 4th line - tr command replaces newline with a space in the end results. (The tagnames are now on one line, separated with spaces.)

The results are stored in a variable (taglist - note the backticks at the beginning and end of the entire command set following the taglist=).

Finally, then, you push the tag list to origin (using a $ to indicate that taglist is a variable).

like image 43
leanne Avatar answered Oct 15 '25 13:10

leanne