tags:

views:

46

answers:

2

With GIT, how can I tell if one commit in my branch is a descendant of another commit?

+1  A: 

This kind of operations relies on the notion of range of revisions detailed in the SO question: "Difference in ‘git log origin/master’ vs ‘git log origin/master..’".

git rev-list should be able to walk back from a commit, up until another if reachable.

So I would try:

git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20

If the last commit displayed is the same than the first commit in the git rev-list command, then it is a commit reachable from the second commit.

If the first commit is not reachable from the second, git rev-list should return nothing.

git rev-list --boundary A..B

would finish by A, if A is reachable from B. It is the same than:

git rev-list --boundary B --not A

,with B a positive reference, and A a negative reference.
It will starts at B and walks back through the graph until it encounters a revision that is reachable from A.
I would argue that if A is directly reachable from B, it will encounter (and display, because of the --boundary option) A itself.

VonC
+3  A: 

If you want to check this programmatically (e.g. in script), you can check if git merge-base A B is equal to git rev-parse --verify A (then A is reachable from B), or if it is git rev-parse --verify B (then B is reachable from A). git rev-parse is here needed to convert from commit name to commit SHA-1 / commit id.

Using git rev-list like in VonC answer is also possibility.


If one of commits you are asking about is a branch tip, then git branch --contains <commit> or git branch --merged <commit> might be better non-programmatic solution.

Jakub Narębski
Excellent. I wasn't so sure of my solution. Yours is more precise. +1
VonC
Possibly the fastest way would be to `git checkout -b quickcheck <more-recent-commit-ID>` and then `git branch --contains <older-commit-ID>` (and then `git branch -D quickcheck` to get rid of the temporary branch).
clee