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

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

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


当前回答

git rev-list --ancestry-path commit1..commit2

我将commit1设置为当前提交,将commit2设置为当前头部,这将返回在commit1和commit2之间构建路径的所有提交的列表。

输出的最后一行是commit1的子元素(在通往commit2的路径上)。

其他回答

我用下面的方法找到了下一个孩子:

git log --reverse --children -n1 HEAD (where 'n' is the number of children to show)
git rev-list --ancestry-path commit1..commit2

我将commit1设置为当前提交,将commit2设置为当前头部,这将返回在commit1和commit2之间构建路径的所有提交的列表。

输出的最后一行是commit1的子元素(在通往commit2的路径上)。

《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使引用指向悬垂提交,以应用其他答案中的技术。

我明白你的意思。让人沮丧的是,有足够多的语法可以转到以前的提交,但没有一个语法可以转到下一个提交。在复杂的历史中,“下一次提交是什么”的问题变得相当困难,但在复杂的合并中,“前一次”提交也会出现同样的困难。在简单的情况下,在具有线性历史记录的单个分支中(即使只是局部地针对一些有限数量的提交),向前和向后移动将是很好的和有意义的。

然而,这样做的真正问题是,子提交没有被引用;它只是一个反向链表。找到子提交需要进行搜索,这并不太糟糕,但Git可能不想把它放入refspec逻辑中。

无论如何,我遇到了这个问题,因为我只是想在历史上一步一步地向前迈进,做测试,有时你必须向前迈进,而不是后退。嗯,经过深思熟虑,我想出了这个解决方案:

在你所处的位置之前选择一个承诺。这可能是一个分支。如果你在分支~10,“git checkout分支~9”,“git checkout分支~8”得到下一个之后,“git checkout分支~7”等等。

如果需要的话,在脚本中递减这个数字应该非常容易。比解析Git版本列表简单得多。