21

How to validate whether the commit with given sha exists in current branch?

There are many ways to parse outputs, but I need optimal way which returns boolean (for usage in bash script).

e.g.

sha=$1
if [ -z `git magic --validate $sha` ]; then
  echo "Invalid commit sha: $sha"
  exit 1
fi
user229044
  • 232,980
  • 40
  • 330
  • 338
takeshin
  • 49,108
  • 32
  • 120
  • 164
  • possible duplicate of [How can I tell if one commit is an ancestor of another commit (or vice-versa)?](http://stackoverflow.com/questions/18345157/how-can-i-tell-if-one-commit-is-an-ancestor-of-another-commit-or-vice-versa) – tavnab Jul 25 '15 at 23:34

6 Answers6

24
git rev-parse --quiet --verify <commit>

Does not actually verify that commit (I guess SHA1 is what is meant) exists. It verifies that there is an object in the database corresponding to the SHA1 provided. That is, if there is a blob or tree object that matches the SHA1, it will report that it exists, even if it is not a commit.

git rev-parse --quiet --verify <sha1>^{commit}

This will verify that the object exists and that it is an object that can be used as a commit (commit or annotated tag).

Janne
  • 249
  • 2
  • 2
4

git cat-file prints information about the objects in the repository. "-e" checks if the object is valid and exits with a 0 status and when invalid exists with a 1.

git cat-file -e 3d68db1028afe27a0055c2234f98fc945b1958f5
echo $?
1
Earle
  • 89
  • 4
4

You can look at the output of

git rev-list HEAD..$sha

If this command fails because the sha1 does not exist at all in the repository, the exit code will be non-zero. If the output is empty, the commit is in the current branch, and if it is non-empty, it is not. So your script would look like

if revlist=`git rev-list HEAD..$sha 2>/dev/null` && [ -z "$revlist" ]; then
    :
fi

In case you already know that $sha really names a commit (as a SHA1 hash or in any other way), this simplifies to

if [ -z "`git rev-list HEAD..$sha`" ]; then
    :
fi
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
4

The rev-list | grep method works fine; there's the tiniest bit of overhead because git has to print out all the SHA1s for grep to see, but it's not really a big deal.

You can also do it with git merge-base if you like - if the merge base of the target commit and the branch is the target commit, the branch contains the target commit:

if [ "$(git merge-base $commit $branch)" = "$commit" ]; then
    ...
fi

Either way you do it, note that rev-list and merge-base are going to be printing out SHA1s, so if the commit you're testing for inclusion is named by a branch or tag, you'll want to use git rev-parse to turn it into an SHA1 first.

Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • Just a tiny note: the POSIX string equally operator is `=`, not `==`. bash will accept both anyway. – Sven Marnach Nov 09 '10 at 22:54
  • @Sven: Thanks, I always forget that. – Cascabel Nov 09 '10 at 23:44
  • 1
    For a small optimization, it's useful to use `git rev-list -qn1 2>/dev/null`, which won't traverse the whole commit tree and will exit with a non-zero exit code if the given commit does not exist. – nvie Nov 15 '12 at 12:17
  • 8
    @nvie If you're trying to verify the existence of a commit, I think the canonical way is `git rev-parse --quiet --verify `. – Cascabel Nov 15 '12 at 15:27
2
git merge-base --is-ancestor $sha HEAD

This tests if $sha is an ancestor commit for the current branch (HEAD), and exits successfully if it is.

In your example,

sha=$1
if ! git merge-base --is-ancestor $sha HEAD; then
  echo "Invalid commit sha: $sha"
  exit 1
fi
Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • This option is available since Git 1.9.0. – Palec Sep 07 '15 at 22:10
  • Correct. v1.9 has been around for about a year and half at the time of this writing. – Paul Draper Sep 07 '15 at 23:03
  • Debian has a 2-year release cycle, and AFAIK it’s not uncommon that oldstable version is in production use. That’s why I find it necessary to state the Git version this feature was included in. – Palec Sep 07 '15 at 23:11
1
git rev-list branch-youre-interested-in | grep -q sha-youre-interested-in

You can use the exit code from grep in conditionals.

For the current branch,

 git rev-list HEAD | grep -q sha-youre-interested-in
Ken Bloom
  • 57,498
  • 14
  • 111
  • 168