Reputation: 61
I am trying for automation in circleci. For that I need to check whether the current branch in master is a tag release or not.
git log -1 --pretty=%B | grep "Tag version release [0-9]\+\.[0-9]\+\.[0-9]_[0-9]\+\.[0-9]\+\.[0-9]\+"
Using the above command I am able to read the log.
But what i need is the tag: commit sld1kf3ja5ls6kj7gi8rogaeknvaerglreun (HEAD -> master, tag: v1.2.3_0.10.101, origin/master, origin/HEAD)
Upvotes: 0
Views: 159
Reputation: 487755
TL;DR: consider using git tag --points-at
, but be aware of its limitations.
The current branch is never a tag, by definition.
In Git, the current branch is the branch name stored in the special name HEAD
. Running git checkout
or, since Git 2.23, git switch
, allows you to pick a branch by name and set that branch as the current branch. To make branch B the current branch, Git will:
HEAD
.So now, after git checkout master
or git checkout develop
, the current branch is master
or develop
, respectively. The current commit is the last commit of the named branch.
If, however, you issue the command git checkout v1.2.3_0.10.101
—or the equivalent git switch
command—the name you requested is a tag name and not a branch name. Git will not write the tag name into HEAD
. Instead, Git resolves the name into a commit hash ID. Then, Git detaches HEAD by making sure that HEAD
no longer contains any name at all. Instead, Git will:
HEAD
.The effect is that you are no longer on any branch at all.
I need to check whether the current branch in master is a tag release or not.
The phrase current branch in master is simply meaningless.
Every commit has a unique hash ID (it's never sld1kf3j...
as the set of letters and digits only includes 0-9
and a-f
, so it's more like badf00d
or cafebabe
or deadbeef
, but longer). That one hash ID means that commit, and no other commit, ever.
Meanwhile, every name holds one hash ID. Multiple names may hold the same hash ID. So if you are on a branch because you checked one out, there is a commit. If you checked out a tag, there is a commit, but you're no longer on a branch.
You can check whether the current commit has one or more names as well. That's what the decoration in git log
does, for instance. But it may have many names:
$ git log -1
commit <hash> (master, develop, feature, tag: v1.0, tag: beta)
This tells you that the current commit is the given hash and that there are two tags and three branch names, all of which would select that commit. The lack of HEAD ->
here implies that while this is the current commit, we probably did not select it via a branch name. (But git checkout --detach master
or git checkout --detach develop
would result in this same situation, so maybe we did use a branch name and simply also used the --detach
option.)
The only really-sure-fire way to be sure that we arrived at this particular commit by some particular git checkout
or git switch
command is to remember the git checkout
or git switch
command we ran. If your system does that, use that. If it doesn't, there is no sure-fire way to deal with this.2
You can, however, check whether one or more tag names point directly to the current commit:
git tag --points-at HEAD
would, in the above example, spill out the two names v1.0
and beta
. Note that it would do this even if we got here by running git checkout master
, though.
If git tag --points-at
prints no names, no tags point to the current commit.
To tell whether HEAD
contains a branch name right now, consider using:
git symbolic-ref HEAD
which prints the full name of the branch if HEAD
contains a branch name:
$ git symbolic-ref HEAD
refs/heads/master
or produces an error if HEAD
is detached:
$ git checkout --detach master
[messages]
$ git symbolic-ref HEAD
fatal: ref HEAD is not a symbolic ref
Note that --points-at
was new for git tag
in Git version 1.7.10, so if your Git is older than this, you would need to upgrade.
1The replace the current commit step consists of, in effect:
The selected commit is now the current commit, thanks to this "rip out all the files from commit X and insert all the files from commit Y instead" action. Note that both git checkout
and git switch
are careful to rip out only files that are "cleanly saved" in the current commit: the checkout or switch will fail, with an error, if this would lose data. You can, of course, force the switch with -f
/ --force
.
2If reflogs are enabled, the reflog has much of the information you might want. But the points-at method is probably better.
Upvotes: 3