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.
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.
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.
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.
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.
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.
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.
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:
<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":
If you make a lightweight tag on a commit, git rev-parse ^{tag} would actually parsing and dereferencing the commit itself, not the tag.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With