Reputation: 4900
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.
Upvotes: 52
Views: 8957
Reputation: 1323263
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.
Upvotes: 10
Reputation: 311308
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.
Upvotes: 32