ref^指的是在ref之前的提交,那么在ref之后的提交呢?

例如,如果我签出12345,我如何签出下一次提交?

是的,Git是一个DAG节点指针结构树。我如何找到这个之后的提交?


当前回答

如果你心中没有特定的“目的地”提交,而是想查看可能在任何分支上的子提交,你可以使用这个命令:

git rev-list --children --all | grep ^${COMMIT}

如果你想看到所有的子结点和孙子结点,你必须递归地使用rev-list——children,如下所示:

git rev-list --children --all | \
egrep ^\($(git rev-list --children --all | \
           grep ^${COMMIT} | \
           sed 's/ /|/g')\)

(只提供孙辈的版本将使用更复杂的sed和/或cut。)

最后,你可以输入一个log——graph命令来查看树结构,如下所示:

git log --graph --oneline --decorate \
\^${COMMIT}^@ \
$(git rev-list --children --all | \
  egrep ^\($(git rev-list --children --all | \
             grep ^${COMMIT} | \
             sed 's/ /|/g')\))

注意:上面的命令都假设你已经将shell变量${COMMIT}设置为你感兴趣的子提交的某个引用(分支,标签,sha1)。

其他回答

《Hudson》(现在的Jenkins)的创造者Kohsuke Kawaguchi(2013年11月)写道: Kohsuke / git-children-of:

给定一个提交,找到该提交的直接子节点。

#!/bin/bash -e
# given a commit, find immediate children of that commit.
for arg in "$@"; do
  for commit in $(git rev-parse $arg^0); do
    for child in $(git log --format='%H %P' --all | grep -F " $commit" | cut -f1 -d' '); do
      git describe $child
    done
  done
done

正如这个线程所说明的,在一个基于DAG(有向无环图)表示的历史的VCS中,没有“一个父”或“一个子”。

        C1 -> C2 -> C3
      /               \
A -> B                  E -> F
      \               /
        D1 -> D2 ----/

提交的顺序是通过“拓扑顺序”或“日期顺序”来完成的(参见GitPro书籍)。

但是从Git 1.6.0开始,你可以列出提交的子对象。

git rev-list --children
git log --children

注意:对于父提交,你有同样的问题,后缀^ to一个修订参数表示该提交对象的第一个父。^<n>表示<n>的第1个父节点(即rev^等同于rev^1)。

如果你在分支foo上,并发出“git merge bar”,那么foo将是第一个父节点。 例如:第一个父节点是你合并时所在的分支,第二个父节点是你合并的分支上的提交。

现有的答案假设您有一个包含您正在寻找的提交的分支。

在我的例子中,我正在寻找的提交不在git rev-list中——因为没有分支包含它。

我最终通过gitk -reflog手动查看。

如果你在reflog中也找不到你的commit,试试:

Git FSCK—完整的列表悬垂(即不在任何分支)提交,或 Git FSCK -lost-found使引用指向悬垂提交,以应用其他答案中的技术。

两个实用的答案:

一个孩子

根据@Michael的回答,我在.gitconfig中修改了子别名。

它在默认情况下按预期工作,而且是通用的。

# Get the child commit of the current commit.
# Use $1 instead of 'HEAD' if given. Use $2 instead of curent branch if given.
child = "!bash -c 'git log --format=%H --reverse --ancestry-path ${1:-HEAD}..${2:\"$(git rev-parse --abbrev-ref HEAD)\"} | head -1' -"

缺省情况下,它通过跟随祖先一步到当前分支的顶端(除非另一个类似提交的参数作为第二个参数)来给HEAD的子节点(除非给出另一个类似提交的参数)。

如果需要短散列形式,请使用%h而不是%h。

多个孩子

使用分离的HEAD(没有分支)或获取所有子结点,而不考虑分支:

# For the current (or specified) commit-ish, get the all children, print the first child 
children = "!bash -c 'c=${1:-HEAD}; set -- $(git rev-list --all --not \"$c\"^@ --children | grep $(git rev-parse \"$c\") ); shift; echo $1' -"

将$1更改为$*以打印所有子节点。

您还可以更改—全部更改为一个提交,只显示作为该提交的祖先的子节点—换句话说,只显示给定提交“方向”的子节点。这可以帮助您将输出从多个子节点缩小到一个子节点。

要列出所有的提交,从当前提交开始,然后是它的子提交,等等-基本上是标准的git日志,但在时间上相反,使用类似于

git log --reverse --ancestry-path 894e8b4e93d8f3^..master

其中894e8b4e93d8f3是您想要显示的第一个提交。

注意:当使用DOS命令提示符时,必须转义插入符号:

git log --reverse --ancestry-path 894e8b4e93d8f3^^..master

如果你心中没有特定的“目的地”提交,而是想查看可能在任何分支上的子提交,你可以使用这个命令:

git rev-list --children --all | grep ^${COMMIT}

如果你想看到所有的子结点和孙子结点,你必须递归地使用rev-list——children,如下所示:

git rev-list --children --all | \
egrep ^\($(git rev-list --children --all | \
           grep ^${COMMIT} | \
           sed 's/ /|/g')\)

(只提供孙辈的版本将使用更复杂的sed和/或cut。)

最后,你可以输入一个log——graph命令来查看树结构,如下所示:

git log --graph --oneline --decorate \
\^${COMMIT}^@ \
$(git rev-list --children --all | \
  egrep ^\($(git rev-list --children --all | \
             grep ^${COMMIT} | \
             sed 's/ /|/g')\))

注意:上面的命令都假设你已经将shell变量${COMMIT}设置为你感兴趣的子提交的某个引用(分支,标签,sha1)。