Referencing the child of a commit in Git

后端 未结 10 1081
失恋的感觉
失恋的感觉 2020-11-28 08:37

If you want to move the HEAD to the parent of the current HEAD, that\'s easy:

git reset --hard HEAD^

But is there

相关标签:
10条回答
  • 2020-11-28 09:01

    The above method using git rev-list --all considers all available commits, which can be a lot and is often not necessary. If the interesting child commits are reachable from some branch, the number of commits that a script interested in child commits needs to process can be reduced:

    branches=$(git branch --contains $commit| grep -v '[*] ('| sed -e 's+^..++')
    

    will determine the set of branches that $commit is an ancestor of. With a modern git, at least version 2.21+, this should do the same without the need for sed (untested):

    branches=$(git branch --format='%(refname:short)' --contains $commit| grep -v '[*] (')
    

    Using this set, git rev-list --parents ^$commit $branches should yield exactly the set of all parent-child relationships between $commit and all branch heads that it is an ancestor of.

    0 讨论(0)
  • 2020-11-28 09:05

    Based partly on Paul Wagland's answer and partly on his source, I am using the following:

    git log --ancestry-path --format=%H ${commit}..master | tail -1
    

    I found that Paul's answer gave me the wrong output for older commits (possibly due to merging?), where the primary difference is the --ancestry-path flag.

    0 讨论(0)
  • 2020-11-28 09:07

    Based on the answer given in How do I find the next commit in git?, I have another solution that works for me.

    Assuming that you want to find the next revision on the "master" branch, then you can do:

    git log --reverse ${commit}..master | sed 's/commit //; q'
    

    This also assumes that there is one next revision, but that is kind of assumed by the question anyway.

    0 讨论(0)
  • 2020-11-28 09:10

    Very probably not the fastest possible solution, but it does what I need:

    #!/bin/bash
    
    REV=$1
    
    if [[ -z "$REV" ]]; then
        echo "Usage: git-get-child  []"
        exit
    fi
    
    HASH=$(git rev-parse $REV)
    
    NUM=$2
    
    if [[ -z "$NUM" ]]; then
        NUM=1
    fi
    
    git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s/\([^ ]*\) .*$/\\1/p"
    

    The git rev-list --all --parents does exactly what I need: it iterates over all reachable commits, and prints the following line for each:

    SHA1_commit SHA1_parent1 SHA1_parent2 etc.

    The space in the grep expression ensures that only those lines are found where the SHA1 in question is a parent. Then we get the nth line for the nth child and get the child's SHA1.

    0 讨论(0)
  • 2020-11-28 09:11

    You can use gitk ... since there can be more than one child there is probably no easy way like HEAD^.

    If you want to undo your whole operation you can use the reflog, too. Use git reflog to find your commit’s pointer, which you can use for the reset command. See here.

    0 讨论(0)
  • 2020-11-28 09:14

    It depends on what you're asking. There could be an infinite number of children of the current head in an infinite number of branches, some local, some remote, and many that have been rebased away and are in your repository, but not part of a history you intend to publish.

    For a simple case, if you have just done a reset to HEAD^, you can get back the child you just threw away as HEAD@{1}.

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