7

I need to find out if a ref to a commit exists. One thing that almost works is git show which sometimes returns non-zero if the ref does not exist. However, it also accepts paths within the current source tree. So if I have a file named master but the ref master does not exist, git show succeeds. I have not been able to find any more specific commands.

I would like the method to accept:

  • Names of branches
  • Commit hashes
  • Tags
  • Keywords like HEAD

Edit: I'm doing this because I want to preform sanity checks on user input programatically.

timthelion
  • 2,636
  • 2
  • 21
  • 30

4 Answers4

11

You can use git rev-parse with the --verify flag to parse various refs and decode them to their SHA-1 hash value. This will get rid of all invalid refs and also file paths:

$ git rev-parse --verify HEAD
a93775d7fcd9bf27bbd89ee69e84a03e06223e9b
$ git rev-parse --verify HEAD~2
4100b19c32fac3e2c0838c85d180cd4f50500c2f
$ git rev-parse --verify master
e88352936f4ffc703cdfb0da95ad5592456feb0b
$ git rev-parse --verify origin/master
e88352936f4ffc703cdfb0da95ad5592456feb0b
$ git rev-parse --verify README.md
fatal: Needed a single revision
$ git rev-parse --verify doesnotexist
fatal: Needed a single revision

Note that this will unfortunately also accept other object types, e.g. trees:

$ git rev-parse --verify "HEAD^{tree}"
5fdca9a3c0db1e1414229a7b50dac20e4e87a3b8

What you can do is use git cat-file as this operates directly on Git’s object database. So it can only find objects that actually exist. It also parses any kind of revision argument you pass to it, so it can understand various references. By using the -t parameter, it will give you the type of the object you are passing. If that type is a commit, then whatever you passed is a valid way to specify an existing commit:

$ git cat-file -t HEAD
commit
$ git cat-file -t HEAD~2
commit
$ git cat-file -t master
commit
$ git cat-file -t origin/master
commit
$ git cat-file -t README.md
fatal: Not a valid object name README.md
$ git cat-file -t doesnotexist
fatal: Not a valid object name doesnotexist
$ git cat-file -t "HEAD^{tree}"
tree

So just check whether that returns commit and you seem to have a good way to verify whether a user input is a valid commit reference.

poke
  • 369,085
  • 72
  • 557
  • 602
  • Thank you! It appears that "git cat-file -t" is what I was looking for :) – timthelion Jan 06 '16 at 09:37
  • 1
    Please note, that it will return `tag` for tags, so you would need to check if it is either `commit` or `tag` in the output. – Captain Ahab Mar 22 '16 at 10:03
  • Exactly what I needed! Good for finding out how far you can go back with `HEAD~` e.g. for finding the first commit – xdevs23 Sep 30 '17 at 11:39
  • Note that this won't work for verifying that a _commit ID_ exists. Instead, the help page for `git rev-parse` suggests that `git rev-parse --verify ^{commit}` can be used (or `^{object}` for any type of object). – dan Jul 12 '23 at 17:20
1
git show [options] <object>

can help you if you write more precisely object name as described here. For example there is a note about master:

master typically means the commit object referenced by refs/heads/master. If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell Git which one you mean.

More information about git show

  • That works when I'm at the command line, but what I am doing now is trying to sanitize user input programatically. At the point where my program is preforming the check it doesn't know anything about the input, only that it is a string that was typed in. – timthelion Jan 06 '16 at 09:21
0

So given something that resolves to an existing commit, you want to find all refs that point to it?

The following seems to give what you want:

git show-ref --head --heads --tags | grep `git rev-parse $THING`
BooK
  • 171
  • 4
  • I want to sanity check user input. show-ref actually gets me half way there. I can now check if a branch name or other reference, like HEAD, exists/is valid. I still don't know how to determine if a commit hash exists. – timthelion Jan 06 '16 at 09:16
0

If you want to check all the branches, you can use git branch -a to list all the remote and locate branches.

If you want to check all commit hashes, you can use git log to list all commits.

If you want to check all the tags, you can use git tag -l to list all the tag names.

And if you want to know which commit your HEAD point to, you can use git rev-parse HEAD to check. And take this as a reference.

If you want to learn more, you can check the bookPro Git.

Community
  • 1
  • 1
einverne
  • 6,454
  • 6
  • 45
  • 91
  • Does git log actually list all commits or merely the ones that are linked to from HEAD? What about commits in other branches? – timthelion Jan 06 '16 at 09:18