66

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?

aleclarson
  • 18,087
  • 14
  • 64
  • 91

3 Answers3

80

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.)

torek
  • 448,244
  • 59
  • 642
  • 775
  • 3
    When I tried git seems to fetch not only the tag that I specify, but also all historical tags (up to the specified maybe?). Is there a way to limit the number of fetched tags to 1? – Sah Mar 27 '18 at 06:50
  • 5
    @Sah: what command, *precisely*, did you run? Using `--no-tags` tells `git fetch` not to automatically fetch "extra" tags that it will otherwise fetch; using `--tags` tells it to fetch *all* tags. You can also set `remote..tagOpt` in your configuration. – torek Mar 27 '18 at 14:36
  • 3
    It was `git fetch origin refs/tags/1.0.0:refs/tags/1.0.0` that I ran. And `--no-tags` solved my problem. Thanks a lot! – Sah Mar 27 '18 at 17:32
  • OK. Git's tag updates are a bit of a mystery to me: I've dug around in the source code and they are done by special case code, as well as by the normal reference-updating code. The special case code may behave differently in different Git versions. Using `--no-tags` suppresses the special-case code. – torek Mar 27 '18 at 17:40
  • 1
    One thing I would add is if you've already done `git fetch origin refs/tags/1.0.0` before you saw the tip about using `git fetch origin refs/tags/1.0.0:refs/tags/1.0.0`, you can still create the tag with the command `git tag 1.0.0 FETCH_HEAD` (assuming you haven't fetched anything else since). – Dominic LoBue Dec 28 '20 at 22:35
42

I read all the answers, but there is not yet mentioned one syntactic sugar. If you need to fetch only one tag as a tag (to checkout later) you can write, for instance for refs/tags/2.3.18:

git fetch origin tag 2.3.18 --no-tags

This is shortcut for already mentioned:

git fetch origin refs/tags/2.3.18:refs/tags/2.3.18 --no-tags

Of course, you may not use --no-tags if you need other tags (according to the default behavior) or if you already explicitly set --no-tag in the clone command or in tagOpt config option(man git-clone).

git fetch origin tag 2.3.18
Vaishnavi Dongre
  • 241
  • 3
  • 11
Olleg
  • 794
  • 7
  • 7
4

When you specify explicit refs to git fetch, you need to either provide a mapping in your refspec or do what you want with the fetched id's recorded in FETCH_HEAD yourself.

The advantage to having the no-mapping-provided case do no default processing on the fetched refs is, the no-mapping-provided case does no default processing on the fetched refs. You might appreciate

git fetch origin v2.3.18
git tag v2.3.18 FETCH_HEAD    # ← git tag !$ FE<TAB>

when you really only want just the one tag set up in your local repo and not however many dozens of prior tags in the origin repo point into the fetched history.

jthill
  • 55,082
  • 5
  • 77
  • 137