How can we refer to a child of a commit?

后端 未结 2 515
梦如初夏
梦如初夏 2021-01-22 17:18

Given a branch name or a tag name, we can refer to its parent by name~1. Can we refer to one of its children in some way?

Thanks.

相关标签:
2条回答
  • 2021-01-22 17:48

    As chepner said, the information is not directly available, as Git only stores backwards links. A parent commit always exists when its child is created, but its children do not exist when the parent is created. Once a commit has been created, nothing about it can ever be changed, so there's no way to hook it up to its children.

    Nonetheless, if you have a direction in mind, you can find the children of some commit in that direction. Here's what I mean: suppose the graph looks like this:

              B--D--E   <-- branch1
             /
    ...--o--A
             \
              C--F--G   <-- branch2
    

    And, suppose you have the name or hash ID of commit A in your paws at the moment. You can find the hash ID of commit B by searching from A in the "branch1" direction, and the hash ID of commit C by searching from A in the "branch2" direction. To do this, use:

    git rev-list --reverse --topo-order --ancestry-path A..branch1
    

    which will list out the hash IDs for commits B, D, and E in that order. Replace branch1 with branch2 to get C, F, and G in that order.

    Be aware that if the graph looks like this:

              B--E   <-- branch1
             /  /
    ...--o--A--D
             \
              C   <-- branch2
    

    you could get either B or D first, in the A..branch1 direction. To check for such situations, instead of (or in addition to) using --topo-order and/or --reverse, collect all the commits along this ancestry path, and for each such commit, check all that commit's parents:

    ahash=$(git rev-parse A^{commit}) # in case A is a branch or tag name, for instance
    for hash in $(git rev-list --ancestry-path $ahash..branch1); do
        if git rev-parse $hash^@ | grep -q $ahash; then
            echo $hash is a child of $ahash
        fi
    done
    

    (this code is untested).

    0 讨论(0)
  • 2021-01-22 17:54

    A Git repository is represented as a DAG (directed, acyclic graph) of commits. Each commit includes one pointer to each of its parents, but no information about what commits have it as a parent. That's why you can only refer to the parents of a commit (name~1, name~2, etc), not the commits that have name as a parent.

    (Most commits have a single parent, but a merge commit is an example of a commit with 2 or more parents, depending on how many branches were involved in the merge.)

    0 讨论(0)
提交回复
热议问题