如何将日志限制为给定提交的所有后代?
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>
为C
时,结果为CDEXY
- 当
<rev>
为D
或X
时,结果为DEXY
(奇怪!)
- 当
<rev>
为E
时,结果为E
我的理解是该命令不会获取 <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?
是;您的 底部提交 差了一个。
详情
因为在您的示例中,提交 D
和 X
是对称的,我们只关注提交 D
并解构命令
git log --all --ancestry-path D^!
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
或其任何祖先,并且您得到提交 D
、E
、X
和 Y
.
如您所见,您的底部提交减少了一个。你真正想要什么运行
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
鉴于历史
X-Y <- feature
/
A-B-C-D-E <- master
我想获取给定提交的后代。一种解决方案似乎是:
git log --all --ancestry-path <ref>^!
但是,行为有点奇怪:
- 当
<rev>
为C
时,结果为CDEXY
- 当
<rev>
为D
或X
时,结果为DEXY
(奇怪!) - 当
<rev>
为E
时,结果为E
我的理解是该命令不会获取 <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?
是;您的 底部提交 差了一个。
详情
因为在您的示例中,提交 D
和 X
是对称的,我们只关注提交 D
并解构命令
git log --all --ancestry-path D^!
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
或其任何祖先,并且您得到提交 D
、E
、X
和 Y
.
如您所见,您的底部提交减少了一个。你真正想要什么运行
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