matthiasbe's answer is fine for many purposes, but for scripting, as long as your Git is not too severely ancient,1, you would generally want to use:
if git merge-base --is-ancestor commit-specifier-1 commit-specifier-2; then
# commit specifier #1 is an ancestor of commit specifier 2
else
# commit specifier #1 is NOT an ancestor of commit specifier 2
fi
as the test. This is because git merge-base --is-ancestor
encodes the result as its exit status, so that you do not have to run a separate test to compare the number to something.
Note that it is possible for one branch tip to be both ahead of and behind another:
$ git rev-list --left-right --count stash-exp...master
1 6473
Here, neither specified commit is an ancestor of the other. However, given these other specifiers:
$ git rev-list --left-right --count master...origin/master
0 103
we see that master
here is strictly behind origin/master
, so that:
$ git merge-base --is-ancestor master origin/master && echo can fast-forward
can fast-forward
which is the same answer you would get from seeing the zero count out of git rev-list --count origin/master..master
:
$ git rev-list --count origin/master..master
0
1git merge-base --is-ancestor
was introduced in Git version 1.8.0. Some systems are still shipping with Git 1.7...