286

I'm having trouble finding out which tag is currently checked out.

When I do:

git checkout tag1
git branch

I can't seem to find out which tag I'm on. It only logs:

* (no branch)
master

Is it possible to find out which tags are checked out? In the above example, this would be tag1.

Zoe
  • 27,060
  • 21
  • 118
  • 148
grm
  • 5,197
  • 5
  • 29
  • 35

7 Answers7

453

Edit

Jakub Narębski has more git-fu. The following much simpler command works perfectly:

git describe --tags

(Or without the --tags if you have checked out an annotated tag. My tag is lightweight, so I need the --tags.)

Original answer

git describe --exact-match --tags $(git log -n1 --pretty='%h')

Someone with more git-fu may have a more elegant solution...

This leverages the fact that git-log reports the log starting from what you've checked out. %h prints the abbreviated hash. Then git describe --exact-match --tags finds the tag (lightweight or annotated) that exactly matches that commit.

The $() syntax above assumes you're using bash or similar.

bstpierre
  • 30,042
  • 15
  • 70
  • 103
  • 32
    Just using `git describe` would show tag name if you are exactly on (annotated) tag, or `--g` if not, where `` is number of commits since ``. – Jakub Narębski Aug 04 '10 at 12:07
  • 1
    @Jakub - Thanks. I added `--exact-match` to my answer seconds before your comment. Nice to know that you can remove it and still get good info from fuzzier input. – bstpierre Aug 04 '10 at 12:09
  • Thanks, this was exactly what I was looking for. Btw, even git-describe --exact-match (without --tags) works for me. – grm Aug 04 '10 at 12:25
  • 3
    Using `git rev-parse HEAD` is a better solution than `git log -n1 --pretty='%h'`... but why you cannot simply write `HEAD` (or nothing, as `git describe` defaults to HEAD)? – Jakub Narębski Aug 04 '10 at 13:06
  • 1
    only Guybrush hates porcelain – vdegenne Jul 22 '17 at 13:31
  • When I use this, I get something like `19.04.0-1-g61dcc8f`; I recognize `19.04.0` as the most recent tag, but where is the other stuff coming from? – user5359531 Apr 29 '19 at 14:34
  • This is a linux-only answer. To do this in Windows, use ``for /F "usebackq delims=" %A in (`git rev-parse HEAD`) do git describe --exact-match --tags %A``, or just use one of the other answers. – cowlinator Feb 20 '20 at 02:41
  • The edited answer is incorrect, it needs the `--exact-match` portion. Being "on a tag" means the commit you're currently on is what that tag references, not that you have changes since that tag. Also there's an easier way to reference the current commit: `git describe --tags --exact-match HEAD` does it on Linux or Windows. – mtalexan Aug 12 '20 at 16:56
  • @user5359531 Official documentation about the tag format in `git describe`: https://git-scm.com/docs/git-describe#_examples . It's composed by user tag, commit distance and short last commit id. – august0490 Mar 29 '21 at 20:32
111

This worked for me git describe --tags --abbrev=0

Edit 2020: As mentioned by some of the comments below, this might, or might not work for you, so be careful!

M K
  • 9,138
  • 7
  • 43
  • 44
99

Show all tags on current HEAD (or commit)

git tag --points-at HEAD
George Pavelka
  • 2,161
  • 11
  • 8
  • 3
    Note that this command does not report an error at the command-line even if the result comes up empty. Bug? It also returns a list if there are multiple tags at that location. It's the best answer but scripters should proceed with caution keeping these caveats in mind. – ingyhere Jan 03 '18 at 20:57
  • Following @ingyhere's comment. Yes it's good information that it does not have an error, and people need to handle the result accordingly. But I wouldn't call it a bug. For my case, "empty if no tags" is valid. Other cases, someone can save it to a variable then [check if it is empty (link to bash instructions)](https://stackoverflow.com/questions/12137431/test-if-a-command-outputs-an-empty-string) – floer32 May 21 '18 at 23:19
  • That meas there are no tags pointing at current HEAD. – George Pavelka Dec 09 '20 at 13:52
  • Annoyingly, "git tag" automagically pipes its output through a pager, which resulted in some head scratching when my python script that shelled out to git came up with "(press RETURN)" as a tag. The fix was: to add "--no-pager" to the git command. – Roy Smith Sep 17 '22 at 17:59
30

git describe is a porcelain command, which you should avoid:

http://git-blame.blogspot.com/2013/06/checking-current-branch-programatically.html

Instead, I used:

git name-rev --tags --name-only $(git rev-parse HEAD)
Daniel Serodio
  • 4,229
  • 5
  • 37
  • 33
Greg
  • 473
  • 4
  • 4
  • 14
    It is returning "undefined" – Stranger Feb 20 '15 at 07:00
  • 5
    This outputs a trailing `^0` for commits which correspond to tags (eg, for tag `1.0` it outputs `1.0^0`). Is there any way of having Git output only `1.0`, or should I use sed for this? – Daniel Serodio Jun 24 '15 at 14:16
  • @DanielSerodio this worked for me in bash with sed installed: `git name-rev --tags --name-only $(git rev-parse HEAD) | sed 's|\([^\^]*\)\(\^0\)$|\1|g'` – hobs Jul 16 '15 at 20:19
  • @DanielSerodio for bare-bones bash this should work: `TAG=$(git name-rev --tags --name-only $(git rev-parse HEAD)) && TAG=${TAG%^0} && echo $TAG` – hobs Jul 16 '15 at 22:57
  • 20
    Just some conceptual nitpicking: I think you inverted the meanings of porcelain and plumbing. It's ok to use porcelain, it's high level and meant for [normal use](https://schacon.github.io/git/git.html). Plumbing ist internal (as the name suggests) and is only not recommended because the git developers reserve the right to change their arguments and output without warning. So your first suggestion is actually the slightly more appropriate one. – Leo Antunes Oct 13 '15 at 15:52
  • 6
    The linked article says to avoid using "git branch" because it doesn't work for this use case. I can't think of any good reason to avoid using git describe. Like Leo says, "Porcelain" commands are the commands you are generally supposed to use. Avoid the plumbing commands unless you really know what you are doing. "git describe" works great. – Danny Oct 28 '15 at 19:33
  • 5
    "Porcelain" commands are the ones you should use, not the ones you should avoid. They are the commands whose output is machine readable and will not change in future versions, so can be relied upon in scripts etc. Non porcelain commands tend to produce more human-readable output, but it may change in future versions e.g. to make it more readable, not because something important has actually changed. – rjmunro Jun 15 '17 at 10:56
  • is the `$(git rev-parse HEAD)` actually necessary? it looks like `name-rev` can figure out what `HEAD` is on its own – kbolino Jun 30 '18 at 18:08
  • According to the main git manpage, `git rev-parse` is also a porcelain command. But as @kbolino notes, it doesn't seem to be necessary here: the `git name-rev` manpage says it can handle ‘any format parsable by `git rev-parse`’. – Pont Oct 08 '18 at 15:23
25

When you check out a tag, you have what's called a "detached head". Normally, Git's HEAD commit is a pointer to the branch that you currently have checked out. However, if you check out something other than a local branch (a tag or a remote branch, for example) you have a "detached head" -- you're not really on any branch. You should not make any commits while on a detached head.

It's okay to check out a tag if you don't want to make any edits. If you're just examining the contents of files, or you want to build your project from a tag, it's okay to git checkout my_tag and work with the files, as long as you don't make any commits. If you want to start modifying files, you should create a branch based on the tag:

$ git checkout -b my_tag_branch my_tag

will create a new branch called my_tag_branch starting from my_tag. It's safe to commit changes on this branch.

mipadi
  • 398,885
  • 90
  • 523
  • 479
12

git log --decorate

This will tell you what refs are pointing to the currently checked out commit.

chriswatrous
  • 189
  • 2
  • 2
2

Here's a fun one for a certain set of use cases. If your repository has versions such as v1.0.0, v1.1.0, v1.1.1 etc, and also shorthand versions such as v1 that point to whatever is the latest v1.x.x, the following will give you a reference to the currently-checked-out commit in relation to the most recent fully versioned tag, with fallbacks if that doesn't work:

git describe --tags --exact-match --match "v*.*.*" \
  || git describe --match "v*.*.*" --tags \
  || git describe --tags \
  || git rev-parse HEAD

So let's say you have the following commits:

* 4444444 (main, origin/main, tag: v2.0.0, tag: v2.0, tag: v2)
* 3333333
* 2222222 (tag: v1.1.0, tag: v1.1, tag: v1)
* 1111111 (tag: v1.0.0, tag: v1.0)
* 0000000

Output of the above command for a few example HEADs:

  • git checkout main -> v2.0.0
  • git checkout 3333333 -> v1.1.0-1-g3333333
  • git checkout 2222222 -> v1.1.0
  • git checkout v1 -> v1.1.0
  • git checkout 0000000 -> 0000000 (full ref)
snazzybouche
  • 2,241
  • 3
  • 21
  • 51