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

时间:2015-07-07 09:43:57

标签: git git-log

鉴于历史

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

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

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

然而,这种行为有点奇怪:

  • <rev>C时,结果为CDEXY
  • <rev>DX时,结果为DEXY(很奇怪!)
  • <rev>E时,结果为E

我的理解是该命令不会使<rev>的所有孩子都得到;相反,它获得父(-ref)的所有孩子。我是对的吗?

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

1 个答案:

答案 0 :(得分:5)

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

据我所知,没有内置的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; DR

  

我的理解是该命令不会使<rev>的所有孩子都得到;相反,它获得父(-ref)的所有孩子。我是对的吗?

是;你的底部提交是一个人。

详细

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

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

根据relevant Git man page

  

后缀为^后跟感叹号与提交提交<rev>相同,然后其所有父项都以^为前缀,以排除它们(及其祖先)。

此外,根据git-log man page

  

--all

     

伪装成refs /中的所有引用都在命令行中列为<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或主服务器可以访问的所有提交的日志,但不包括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