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

6

鉴于历史背景,

      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个回答

7

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

据我所知,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^!

根据相关的Git手册页面

后缀 ^ 加上叹号的意思相当于给定提交 <rev> 和它所有的父提交加上前缀 ^ 以排除它们(及其祖先)。

此外,根据git-log手册页面,

--all

假装所有refs/中的引用都像命令行中列出的<commit>一样。

因此,在您的情况下。
git log --all --ancestry-path D^!

等同于

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

此外,由于从 master 可以到达 D,所以后者的命令简化为:
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

(请注意,提交记录D和X可以用它们的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

很好的解释。现在以上三种情况都清楚了。而且也清楚该命令无法获取所请求的信息(除非是特殊情况)。那么,如何做到呢?如何获取所有基于某个引用的引用? - Henning
太好了!所以主要的区别在于“^D != D^!”因为“D^! == ^D^”,这就是你所说的“差一”的意思。非常感谢! - Henning
1
@Henning 更准确地说,D^!等同于D ^D。不客气! - jub0bs
这引出了另一个问题:我认为我需要修改我的最后一句话。它只有在与“--all --ancestry-path”结合使用时才有效。没有这些选项,“D^!”不会产生与“^D^”相同的结果。但是“D ^D”也不是。因此,“D^!”和“D ^D”不等,对吧?此外,“D ^D”不能与“--ancestry-path”一起使用。错误是“--ancestry-path given but there are no bottom commits”。这一切都太令人困惑了... - Henning
1
@Henning 抱歉,我犯了一个错误。我的意思是:*更准确地说,D^! 等同于 D ^D~*。尝试一下,看看是否会出现“没有底部提交”的错误。 - jub0bs
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接