How to check if the commit exists in a Git repository by its SHA-1
GitGit Problem Overview
In a similar topic https://stackoverflow.com/questions/4127967/validate-if-commit-exists they recommend:
git rev-list HEAD..$sha
If it exits without error code than the commit exists.
But is it efficient enough just for validation?
I was thinking about this option:
git cat-file commit $sha
Is it correct for my task and are there any other ideas?
Git Solutions
Solution 1 - Git
You can just run git cat-file -t $sha
and check it returns "commit". You are right, you don't need to actually print the actual object for that...
I'm not 100% sure that what goes on behind the scene is more efficient, though.
test $(git cat-file -t $sha) == commit
Solution 2 - Git
git cat-file -e $sha^{commit}
From git cat-file
docs:
> -e > Suppress all output; instead exit with zero status if
Solution 3 - Git
git rev-parse -q --verify "$sha^{commit}" > /dev/null
From the git rev-parse
docs:
> --verify
> Verify that exactly one parameter is provided, and that it can be turned into a raw 20-byte SHA-1 that can be used to access the object database. If so, emit it to the standard output; otherwise, error out.
>
> If you want to make sure that the output actually names an object in your object database and/or can be used as a specific type of object you require, you can add the ^{type} peeling operator to the parameter. For
> example, git rev-parse "$VAR^{commit}" will make sure $VAR names an existing object that is a commit-ish (i.e. a commit, or an annotated tag that points at a commit). To make sure that $VAR names an existing object of
> any type, git rev-parse "$VAR^{object}" can be used.
>
> -q, --quiet
> Only meaningful in --verify mode. Do not output an error message if the first argument is not a valid object name; instead exit with non-zero status silently. SHA-1s for valid object names are printed to stdout on
> success.
As a bonus, if you don't suppress the output, you can get the full sha.
Solution 4 - Git
If you are sure that the sha are commits then cat-file -e
can be used for example:
if git cat-file -e $sha 2> /dev/null
then
echo exists
else
echo missing
fi
This is pretty efficient as this is a built-in and doesn't do anything other than checking the sha exists:
return !has_sha1_file(sha1);
Otherwise if it is uncertain that the sha are commit objects you would need to determine the type as with the other answer using git cat-file -t
. This is only slightly less performant as git would have to look at the file information. This isn't as costly as unpacking the whole file.