Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Given a git refname, can I detect whether it's a hash, tag, or branch?

Tags:

git

I'm writing a script that will take in a specification used as the base for creating a branch. Thus, it will have something like this:

git checkout -b $newbranch $startingpoint 

Now, startingpoint can be specified either as a branch name, a tag, or a SHA1.

Later in the script, I need to do different things based on what startingpoint actually is. Is had thought git rev-parse would give me this information, but I cannot seem to bend it to my whim.

Is there a git way, preferably a porcelain, to get the information I seek?

Update

I used the show-ref information to craft the following shell function:

git_ref_type() {     [ -n "$1" ] || die "Missing ref name"      if git show-ref -q --verify "refs/heads/$1" 2>/dev/null; then         echo "branch"     elif git show-ref -q --verify "refs/tags/$1" 2>/dev/null; then         echo "tag"     elif git show-ref -q --verify "refs/remote/$1" 2>/dev/null; then         echo "remote"     elif git rev-parse --verify "$1^{commit}" >/dev/null 2>&1; then         echo "hash"     else         echo "unknown"     fi     return 0 } 

This seems to work well for now, though it's been only very lightly tested.

like image 278
Chris Cleeland Avatar asked Aug 14 '13 03:08

Chris Cleeland


People also ask

Is tag and branch same in git?

The difference between tags and branches are that a branch always points to the top of a development line and will change when a new commit is pushed whereas a tag will not change. Thus tags are more useful to "tag" a specific version and the tag will then always stay on that version and usually not be changed.

How do I check out a git tag?

In order to checkout a Git tag, use the “git checkout” command and specify the tagname as well as the branch to be checked out. Note that you will have to make sure that you have the latest tag list from your remote repository.

How do I see branch tags?

Find Latest Git Tag Available In order to find the latest Git tag available on your repository, you have to use the “git describe” command with the “–tags” option. This way, you will be presented with the tag that is associated with the latest commit of your current checked out branch.

Do git tags belong to a branch?

Tags and branch are completely unrelated, since tags refer to a specific commit, and branch is a moving reference to the last commit of a history. Branches go, tags stay. So when you tag a commit, git doesn't care which commit or branch is checked out, if you provide him the SHA1 of what you want to tag.


2 Answers

You can probably use the show-ref command to do (mostly) what you want. Given some string, if it refers to a tag then...

git show-ref --verify refs/tags/$thestring 

...will be true. If it's a branch name, then...

git show-ref --verify refs/heads/$thestring 

...will be true. If the string fails both of those tests, then...

git rev-parse --verify "$thestring^{commit}" 

...will tell you if it otherwise refers to a commit (which could be a complete SHA1, a partial SHA1, HEAD, or possibly something else that doesn't fall into the previous two categories.

like image 137
larsks Avatar answered Oct 19 '22 11:10

larsks


Note that git 1.8.5 or 1.9 (Q4 2013) will provide for a new way to test if a ref is a tag or not.

Make "foo^{tag}" to peel a tag to itself, i.e. no-op., and fail if "foo" is not a tag.

How to test a revision is a tag? (or "check if a git name is a tag"?)

git rev-parse --verify v1.0^{tag} 

More convenient than: test $(git cat-file -t v1.0) = tag".

See commits 75aa26d and abdb54a1d, by Richard Hansen:

peel_onion(): add support for <rev>^{tag}

Complete the <rev>^{<type>} family of object descriptors by having <rev>^{tag} dereference <rev> until a tag object is found (or fail if unable).

At first glance this may not seem very useful, as commits, trees, and blobs cannot be peeled to a tag, and a tag would just peel to itself.
However, this can be used to ensure that <rev> names a tag object:

$ git rev-parse --verify v1.8.4^{tag} 04f013d $ git rev-parse --verify master^{tag} error: master^{tag}: expected tag type, but the object dereferences to tree type fatal: Needed a single revision 

Users can already ensure that <rev> is a tag object by checking the output of 'git cat-file -t <rev>', but:

  • users may expect <rev>^{tag} to exist given that <rev>^{commit}, <rev>^{tree}, and <rev>^{blob} all exist
  • this syntax is more convenient/natural in some circumstances

However, as mentioned in the comments by mtraceur, that would not work for a lightweight tag (see "creating tags"), which is just name a for an object (usually a commit object).

You would get an error like:

Eexpected tag type, but the object dereferences to tree type

Because, with a lightweight tag, would would be actually parsing a commit, instead of an actual tag.
From "Git Internals - Git References":

https://git-scm.com/book/en/v2/images/data-model-4.png

If you make a lightweight tag on a commit, git rev-parse ^{tag} would actually parsing and dereferencing the commit itself, not the tag.

like image 21
VonC Avatar answered Oct 19 '22 11:10

VonC