Search code examples
gitgit-taggit-ls-remote

How do `ls-remote --refs` vs. cloning then `describe --tags` relate?


Listing the most recent tag of a remote repository produces a different answer from cloning that repository and then describing its tags. E.g.

$ ​git ls-remote --refs git://git.kernel.org/pub/scm/git/git.git | tail -1
dcba104ffdcf2f27bc5058d8321e7a6c2fe8f27e    refs/tags/v2.9.5
$ git clone -q git://git.kernel.org/pub/scm/git/git.git gitdir && cd gitdir && git describe --tags
v2.31.1-606-gdf6c4f7

How do these two kinds of values relate to one another? How are they different?

I understand that "tag names are local" and my question may relate to that, but I think I don't understand that phrase's implications. I did try another suggestion to git fetch --tags before calling describe, to no avail.

What I ultimately want to do is to programmatically find the most stable release or tag if they aren't using releases, and check out that version to build it locally.


Solution

  • TL;DR

    I believe what you want is the first token from the output of git describe --tags.

    Details

    The two commands serve different purposes.

    git ls-remote lists the references on a remote repository, but does not make any promises about the ordering in which they are listed. Sure, the most recent one is typically last, but it's not necessarily the most relevant one, especially if that tag was on a branch that didn't get merged yet.

    git describe, on the other hand, is trying to give you a concise description of HEAD (by default, or the commit you specify) with respect to the most recent tag reachable from there. If you use your tags only for stable commits, then that's probably going to be the tag you want. Then, once it found that tag, it tells you how many more commits are in HEAD, 606 of them in your example, then "g" (not sure why), then the sha1 of HEAD. This is meant to be a human-readable description of any commit, as in, "oh, you're 606 commits ahead of v2.31.1", but also an unambiguous description, since you get the sha1.

    As for adding the --tags option to git describe, you need it if you have tags without annotations, e.g., if some where created using git tag <tagname> <commit> instead of git tag -a <tagname> <commit>. The latter is preferable, since it allows the tagger to describe the contents of the tag, but you can't always count on everyone using it. So it's probably a good idea to add --tags to git describe.

    If your repo only contains tags for stable releases, and those releases are not on a different release branch, and you never have hyphens in your tag names, then this would be the most recent stable release that's a parent of HEAD:

    git describe --tags | sed 's/-.*//'