3

I can refer to backwards revisions with ^ and ~*number*, like 319411a^ or HEAD~3.

Is there any specific syntax to refer to forward commits (something like the syntax above)?

I'm NOT asking if it is possible to simply refer to forwards commits. I'm asking if it's possible to refer to forward revisions without manually finding out the desired revision SHA1.

talles
  • 14,356
  • 8
  • 45
  • 58
  • possible duplicate of [How do I find the next commit in git?](http://stackoverflow.com/questions/2263674/how-do-i-find-the-next-commit-in-git), also http://stackoverflow.com/questions/1761825/referencing-the-child-of-a-commit-in-git – Hasturkun Sep 09 '13 at 13:22
  • @Hasturkun none of these questions refer to a syntax for it. With both you have to find out the desired SHA1 – talles Sep 09 '13 at 14:24
  • @talles: There is no syntax for child/descendant commits, AFAIK. (also, the linked question refers to the syntax.) I'd also like to note [this answer](http://stackoverflow.com/a/2263779/20270) and suggest that you read the [gitrevisions manpage](https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html) – Hasturkun Sep 09 '13 at 14:43

2 Answers2

2

There isn't; but, using git rev-list and then further work, it would be possible to find items that point back to a given commit. You must first choose some starting point (probably --all), then exclude the target rev and its parents:

git rev-list --all --not rev

This of course produces a long list of revs, many of which are uninteresting, so it needs further filtering: you want those where a parent of the rev is rev.

This shell script (with no error checking etc) only handles first-parent:

target=$(git rev-parse $1)
git rev-list --all --not $target |
    while read rev; do
        if [ $(git rev-parse --verify --quiet $rev^) = $target ]; then
            echo $rev
        fi
    done

but it should be pretty obvious how to fancy it up from there (see the documentation for git rev-list). Use:

git rev-list -1 --parents $rev

to turn a single rev into a list of "the rev and its parents", for merges, e.g.:

set -- $(git rev-list -1 --parents $rev)
shift # discard the rev itself
echo there are $# parents and they are $*
for parent do
    if [ $parent = $target ]; then
        echo $rev has $target as a parent
    fi
done

Edit: in a large repo, you can get a better starting point with git branch --contains (as noted by RainerBlome in "referencing the child of a commit". Note that you need to parse away the * indicating current branch, and if you have HEAD "detached" the "current branch" is "no branch" and you might want to add HEAD as a starting point. Then, git rev-list --parents | grep ... is a quick way to find desirable refs. I've used these suggestions to improve performance, etc.

Here's a complete script, with some error checking too; lightly tested.

#! /bin/sh
#
# git-rev-list-children.sh

find_branches()
{
        local target="$1"

        set -- $(git branch --contains $target |
            sed -e 's/^\* (.*)/HEAD/' -e 's/^[* ] //')
        case $# in
        0) echo "there are no branches containing $revname"; return 1;;
        esac
        echo $@
}

find_children()
{
        local target="$1"
        shift

        git rev-list --parents "$@" ^$target | grep " $target" |
            while read line; do
                set -- $line
                echo $1
            done
}

# add option parsing (--short?) here if desired
case $# in
0) echo "usage: git-rev-list-children <rev> ..." >&2; exit 1;;
esac

for revname do
        target=$(git rev-parse "$revname") || exit 1
        set -- $(find_branches "$revname" || exit 1)
        find_children "$target" "$@"
done
Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
0

Git commit objects only have a parent pointer, and traversal is backwards only. Commit may or may not have one or more "forward" commits.

Tero Tilus
  • 571
  • 1
  • 3
  • 11