Using Git describe without tags

Yes, but it's not necessarily a good idea. There is a --all option, which will search branch names—or in fact, all references—as well, but if you use that, you might also need --long.

Description

The central feature of git describe output is that it starts with a name that is (or should be) human-readable:

v1.2.3

To this, Git will, if necessary, add a suffix indicating that the current (or requested) commit is not quite the one named by this string. The suffix tells both you and Git how much to deviate from the tag. If there is no suffix, the tag itself names the commit. Since tags never1 move, if we have that name, we are guaranteed2 to find the correct commit using that name.

With a repository with no tags and no --always:

$ git describe
fatal: No names found, cannot describe anything.

If we add --all, however, we might get this:

$ git describe --all
heads/master

This is a human-readable name, but there is a problem with it: it does not uniquely identify one particular commit, because branch names do move. Once I make a new commit in this repository, refs/heads/master now names a different commit.

Since the usual intent of one of these outputs from git describe is to provide a human-readable but exact-commit-specifying ID, a branch name, which is never that exact, is not necessarily a good thing.

You can add --long:

$ git describe --all --long
heads/master-0-g2cbd83f

This now uses the -g... suffix to specify a prefix of the actual hash ID. Now Git can verify that master itself has not moved, or if it has, you can use the 2cbd83f string to find the commit.


1Well, hardly ever. See the git-tag documentation on when and why and why not to move a tag.

2Guaranteed to the extent that tags have not moved, anyway.


An easy way to do this is to combine --always with the -exclude option, using a glob pattern of *, to exclude all tags from consideration. Since it won't find any non-excluded tags, describe will fall back to just the abbreviated sha1 plus optionally "-dirty" and so on.

$ git describe --always --dirty --abbrev=5 
2018.02-rc1-58-gca0e6
$ git describe --always --dirty --abbrev=5 --exclude '*'
ca0e6

Tags:

Git