In a linear history, two commits A and B can have one of three states:
Git's nonlinear history allows for four additional options
I'm not sure how to achieve the last two without using graft points, but it could happen.
What I'm unsure of how to accomplish is a determination of this relationship in a simple manner--at the moment I can only think of a somewhat odd rev-list
and solution where one tests each case individually:
[[ "$a" = "$b" ]] && echo "same"
git rev-list "$b" | grep -q "$a" && echo "a before b"
git rev-list "$a" | grep -q "$b" && echo "b before a"
cat <(git rev-list "$a") <(git rev-list "$b") | sort | uniq -cd | grep -q 2 && echo "A and B share parents"
cat <(git rev-list --children "$a") <(git rev-list --children "$b") | sort | uniq -cd | grep -q 2 && echo "A and B share children"
There has to be a better, gittier way of doing this, so what is it?
Checking for parent-child relation is easy, use git merge-base
. If the result is one of your commits, it's a parent, the other is a child.
I suggest ignoring the case when commits don't have a common ancestor. Sure, this can happen, but I'm not aware of any valid use-cases for this. I mean, you are solving a real problem for a real project, I'm sure you can assume that this won't happen. BTW, merge-base
will exit with an error, and it's the only situation when a merge-base doesn't exist, so you still can detect this case.
Finding children for a commit is just impossible. Absoultely. You can't do that reliably. A commit has a “parent” reference, but it doesn't have “child” references. rev-list --children
does a completely different thing, it has nothing to do with what you want. You’ll have to refine your problem.
What I can suggest instead is using git branch --contains <commit>
or git tag --contains <commit>
which will only list those branches/tags from which you can reach your commit.
Alternatively you can look at git for-each-ref
that will allow you to test if a commit is reachable from any of your branches/tags.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With