In a linear history, two commits A and B can have one of three states:
[[ "$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"
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.