find out if a git commit was checked in before or after another commit given the hashes

Things, as you note, aren't so simple in Git. In particular, the definition of "before" and "after" need a little more clarification.

If you trust the people committing to your repository not to mess with timestamps, and you already know both commits are on the same branch, you can compare the timestamps of the commits and just see which one is earlier. Use the following command for each commit, and compare the result.

git log -1 --format='%ci' <commit>

With Git, you can't necessarily trust the timestamps, however, since unlike Subversion there isn't a central repository with a job of producing them. You also can't be sure that two commits are on the same branch (although that problem also exists with Subversion).

To avoid those problems, talk about whether one commit is an ancestor of another, rather than whether it comes before or after it. In the following commit graph, B and C are ancestors of A, while B is not an ancestor of C nor vice versa:

B    (master)
| C  (branch)
|/
A    (root)

To determine whether commit A is an ancestor of commit B, use the following command (based on an article at git ready):

git rev-list <commitA> | grep $(git rev-parse <commitB>)

The first part lists all the commits that are ancestors of commit A; the second part gets the full hash of commit B, then searches the ancestor list for that commit. If you see any output, commit A is an ancestor of commit B. Swap the arguments to work out if commit A is an ancestor of commit B instead.

This second form is slower, but gives you absolute certainty that one commit is an ancestor of another.


git merge-base has a flag for that. It simply returns a 0/1 exit code.

git merge-base --is-ancestor <commit> <commit>

git rev-list --count can help. Supposing 110a187 comes 4 commits before 5d41af1, then:

 $ git rev-list --count 110a187..5d41af1
4
 $ git rev-list --count 5d41af1..110a187
0

Thus something like:

test $(git rev-list --count $a..$b) == 0 && \
       echo "$a is not an ancestor of $b"

Tags:

Git