Fetch a single tag from remote repository

aleclarson picture aleclarson · Jul 27, 2017 · Viewed 23.1k times · Source

This command fetches all tags:

git fetch origin --tags

This command fetches a specific tag:

git fetch origin refs/tags/1.0.0

But that doesn't let me do:

git checkout tags/2.3.18

How can I fetch a single tag and then perform a checkout?

Answer

torek picture torek · Jul 27, 2017

git fetch origin refs/tags/1.0.0

This fails because it doesn't write a local reference: it obtains the remote's refs/tags/1.0.0, and any tag object(s), commits, etc., required to go with it; it drops those into FETCH_HEAD (as all git fetch commands always do); and ... that's it. It never creates reference refs/tags/1.0.0 in your repository, even though it got everything it needed to do so.

To make it create such a tag if it does not yet exist:

git fetch origin refs/tags/1.0.0:refs/tags/1.0.0

The name on the right of the colon is the name your Git will use in your repository. You could turn this tag into a branch named wacky, for instance, by naming it refs/heads/wacky. (There's no reason to do this. I am describing this just for illustration.)

This is a non-forced fetch, so if you already have a refs/tags/1.0.0, your Git will refuse to update your reference. If you wish to overwrite any existing 1.0.0 tag, use:

git fetch origin +refs/tags/1.0.0:refs/tags/1.0.0

If you wish to fetch all tags, with or without overwriting:

git fetch origin 'refs/tags/*:refs/tags/*'

with or without a leading plus sign. (Note: the quote marks are just to protect the * from your shell. The plus sign may go inside or outside the quotes. In fact, the quotes themselves can go anywhere as long as they surround all asterisks or other shell meta-characters:

refs/tags/'*:refs/tags/*'

or you can use backslashes instead:

refs/tags/\*:refs/tags/\*

In all cases we are just protecting the sensitive asterisk from the shell's "asterisks are tasty, let's eat them" functions.)