查找具有给定祖先的提交
Posted
技术标签:
【中文标题】查找具有给定祖先的提交【英文标题】:Find commits with given ancestors 【发布时间】:2018-10-08 19:48:13 【问题描述】:在某一时刻,我的 git 存储库包含以下结构:
A1 A2 A3
o-----o-----o
\ \
o X o Y
B1 B2/ B3/
o-----o-----o
\
o Z
C1 C2/
o-----o
我正在尝试检索作为多个指定提交的后代的最早提交。决胜局将是提交日期。例如:
descendant A1 B2 -> X
descendant A2 B3 -> Y
descendant A1 C1 -> nothing
合并提交可能有两个以上的父级。我找到了很多关于 git merge-base
的文档,它几乎完成了相反的任务,但找不到任何至少可以返回我可以排序的后代列表的函数。
【问题讨论】:
Git 只跟踪提交的 parents,而不跟踪子项。仅给定A1
和 B2
,除了检查 every 提交以查看它是否具有 A1
和 B2
作为祖先之外,没有其他方法可以找到它们的共同后代。
添加到@chepner 的评论中,这个术语是 DAG(有向无环图)。每个节点之间的边是一种方式。
【参考方案1】:
这是我经过更多研究后设法拼凑的内容。这很丑陋,可能非常效率低下,但看起来很有效。
#!/bin/bash
common_descendants=$(git rev-list --ancestry-path --all $1.. | sort)
shift
while [ $# -ne 0 ]; do
common_descendants=$(
echo "$common_descendants"
| comm -12 --nocheck-order - <(
git rev-list --ancestry-path --all $1.. | sort
)
)
shift
done
git rev-list --reverse --date-order --no-walk $common_descendants | head -n 1
它使用git rev-list --ancestry-path --all
依次查找每个请求提交的所有后代。
这些列表在sort
和comm
的帮助下相交以获得候选提交列表。
最后,git rev-list --ancestry-path --all
按提交日期排序,head -n 1
选择最旧的。
【讨论】:
--ancestry-path
会得到与我建议的结果相似的结果:在这里,您使用 HEAD
作为枚举向后运行的点,然后还丢弃既不是 @ 祖先的提交987654329@ 也不是您的限制提交的后代。但是,您排除了特定的限制提交本身,这可能是最低共同后代的答案。
@torek 在点击之前我得再考虑一下。我没有考虑到这些提示对于以正确的方式遍历图表很有用。谢谢指点!【参考方案2】:
作为chepner commented,Git 只有反向指针。 查找提交 C 的后代必须转化为一个新的不同的问题,而是:查找提交 T 的祖先,其自身具有提交 C 作为祖先。 这里 T 是一个提示提交,或者在您的情况下,可能是许多提示提交——所有分支,可能还有所有标签和所有其他引用。
git rev-list
命令适合解决问题。特别是,您可以让它遍历从提示(后代)到父母的图形,但收集在此过程中遍历的边,然后使用 --children
反转它们。正如the documentation 所说,这可以实现父级重写和历史简化。
(我认为您需要在您选择的任何起始提示提交上运行git rev-list --children
,并自己解析其输出以应用其他约束。您可以使用您正在搜索的提交的父级作为停止点,使用the ^<em>hash</em>^@
gitrevisions syntax,用于剪切图迭代。请注意,这实际上是领先的^
,类似于--not
,但局部而不是全局,应用于rev^@
。)
【讨论】:
以上是关于查找具有给定祖先的提交的主要内容,如果未能解决你的问题,请参考以下文章