【发布时间】:2017-01-09 10:03:17
【问题描述】:
给定两个 git 提交,我如何确定(理想情况下使用管道命令)它们之间的历史记录是否是线性的?
也就是说,我想知道我是否有这个:
A-B-C-D-E-F-G
而不是这样:
/-C-\
A-B -E-F-G
\-D-/
【问题讨论】:
标签: git
给定两个 git 提交,我如何确定(理想情况下使用管道命令)它们之间的历史记录是否是线性的?
也就是说,我想知道我是否有这个:
A-B-C-D-E-F-G
而不是这样:
/-C-\
A-B -E-F-G
\-D-/
【问题讨论】:
标签: git
git log --min-parents=2 只会显示至少有 2 个父节点的提交(例如:合并提交)
你可以运行:
# for esthetics : --oneline will output one single line per filtered commit
git log --oneline --min-parents=2 A..G
# if output is empty : linear history
# and :
git log --oneline --min-parents=2 A..G | wc -l
# should give you the number of merge commits between A and G
【讨论】:
--min-parents 实际上是git rev-list 命令的标志,而git rev-list 有一个内置的--count 标志(用于统计选定提交的数量)。
--min-parents 和--count 处理与git log 共享,尽管--count 与git log 没有意义(因此它会被忽略)。
git rev-list --min-parents=2 --count A..G
将给出具有多个父级的提交数。 计数“0”表示线性历史记录。
【讨论】:
如果您愿意在比瓷器更高级别的东西上妥协,您可以使用gitpython,寻找与一个或多个父母的提交。
import git
def is_linear(commit):
ncommits = len(commit.parents)
if ncommits == 0:
return True
elif ncommits == 1:
return is_linear(commit.parents[0])
else:
return False
repo = git.Repo('.')
print is_linear(repo.commit())
【讨论】:
“Between”在图表中是一个模糊的概念。
如果您有类似示例的内容,LeGEC's answer 很好(尽管我会将其进一步简化为 git rev-list --count --min-parents=2 A..G 并检查非零结果)。
但假设图形片段如下所示:
A--B--C
\
G
/
D--E--F
A..G 是否被认为是线性的?这里A 是root 提交,但这并不重要,我们也可以使用B..G 或C..G。这里的问题是还有另一个根提交D,可以从G 访问,但不是A 的后代。属于“可从G 访问,不包括可从A 访问的提交”的提交集中的合并提交的提交是G 本身。或者:
A--B--C--G
/
D--F
/
E
这里有三个根提交,A、D 和 E。从G 可到达的提交集减去从A 可到达的集留下所有B、C、D、E、F 和G,以及C和 F 是合并提交。
如果您希望将测试限制为“作为A 的后代和G 的祖先的提交,包括G 但不包括A 本身”,请将--ancestry-path 添加到合并检查中:
git rev-list --count --min-parents=2 --ancestry-path A..G
这会将您示例中的嵌入循环计为非线性,但将我的第二个片段计为线性(例如,提交C 和F 不是最后一个图中A 的后代)。我的第一个案例在这里不会被认为是线性的,因为选择了提交 G 并且是合并提交,因此对于这种特殊情况,您必须使用 A..G^@ 作为您的范围。 (这是较早前的轻微修正:我们希望G 的所有父母,而不仅仅是第一个;我们将依靠--ancestry-path 来选择正确的父母。)
【讨论】: