如何将日志限制为给定提交的所有后代?

How can I limit the log to all the descendants of a given commit?

鉴于历史

      X-Y    <- feature
     /
A-B-C-D-E    <- master

我想获取给定提交的后代。一种解决方案似乎是:

git log --all --ancestry-path <ref>^!

但是,行为有点奇怪:

我的理解是该命令不会获取 <rev> 的所有子项;相反,它获取 parent-of(ref) 的所有子代。我说得对吗?

这是不直观的、容易出错的,而且坦率地说,这很烦人。我应该如何命令 运行,以便将日志限制为给定提交的后代。

如何将日志限制为给定修订的所有后代

据我所知,没有内置的 Git 命令可以做到这一点。但是,您快完成了。尝试

git log --all --ancestry-path ^<rev>

相反。那应该将日志限制为 <rev> 的后代;请注意,严格来说,<rev> 不是其自身的子项,因此不会被列出。

例如,在我的玩具仓库中(我复制了你的;请参阅我的答案的底部),

git log --all --ancestry-path ^D

限制日志提交 E,并且

git log --all --ancestry-path ^X

限制日志提交 Y

git log --all --ancestry-path D^! 怎么了?

TL;博士

My understanding is that the command does not get all children of <rev>; instead, it gets all children of parent-of(ref). Am I right?

是;您的 底部提交 差了一个。

详情

因为在您的示例中,提交 DX 是对称的,我们只关注提交 D 并解构命令

git log --all --ancestry-path D^!

根据 relevant Git man page,

A suffix ^ followed by an exclamation mark is the same as giving commit <rev> and then all its parents prefixed with ^ to exclude them (and their ancestors).

此外,根据git-log man page

--all

Pretend as if all the refs in refs/ are listed on the command line as <commit>.

因此,在你的情况下

git log --all --ancestry-path D^!

等同于

git log --ancestry-path D ^C feature master

此外,因为 D 可以从 master 到达,后面的命令减少到

git log --ancestry-path ^C feature master

这给出了所有可从 feature 或 master 访问的提交的日志,但不包括 C 或其任何祖先,并且您得到提交 DEXY.

如您所见,您的底部提交减少了一个。你真正想要什么运行

git log --ancestry-path ^D feature master

相同
git log --all --ancestry-path ^D

测试

以下命令重新创建您的玩具存储库:

$ mkdir gittest
$ cd gittest/
$ git init

$ printf "A\n" > README
$ git add README
$ git commit -m "A"

$ printf "B\n" >> README
$ git commit -am "B"

$ printf "C\n" >> README
$ git commit -am "C"

$ git branch feature

$ printf "D\n" >> README
$ git commit -am "D"

$ printf "E\n" >> README
$ git commit -am "E"

$ git checkout feature
$ printf "X\n" >> README
$ git commit -am "X"

$ printf "Y\n" >> README
$ git commit -am "Y"

$ git log --all --oneline --graph --decorate
* e234427 (HEAD -> feature) Y
* cf98c6b X
| * b3d493a (master) E
| * e2bb266 D
|/  
* dfe0267 C
* 0be7d42 B
* 674356e A

(请注意,提交 DX 可以由它们的 SHA 引用,或者更简单地说,分别由 master~feature~ 引用。)

您建议的命令(我添加了 --oneline 标志,以减少输出)确实 没有 将日志限制为给定提交的后代:

# master~ = D
$ git log --all --ancestry-path --oneline master~^!
e234427 Y
cf98c6b X
b3d493a E
e2bb266 D

# feature~ == X
$ git log --all --ancestry-path --oneline feature~^!
e234427 Y
cf98c6b X
b3d493a E
e2bb266 D

但我建议的是:

# master~ == D
$ git log --all --ancestry-path --oneline ^master~
b3d493a E

# feature~ == X
$ git log --all --ancestry-path --oneline ^feature~
e234427 Y