如何查看 Git 仓库中的 DAG 数量及每个 DAG 相关的分支?

3
我知道你可以通过将--orphan选项传递给git-checkout来创建Git中的孤立分支,这实际上会在Git存储库中创建两个单独的DAG,因为孤立分支与主分支的历史记录没有连接。然而,如果创建了多个孤立分支,有没有办法找出给定仓库中有多少个DAG?
此外,有没有办法找出存储库中哪些分支(head refs)指向哪个DAG?也就是说,你能否根据它们所指向的提交所在的DAG将分支分组?
这个问题更多是假设性的,而不是实际应用,但我仍然很好奇。
2个回答

6
git rev-list --all --max-parents=0

将找到所有的根。

git log --all --ancestry-path ^$root --pretty=%D --simplify-by-decoration

这将找到所有引用特定根的引用(为了得到机器可读格式,您需要一些抓取,最简洁的方法是使用 GNU 的 awk 1 RS='\n+| -> |, ')。

因此,这将把追溯到每个根的提示集转储到tips-$root中:

roots=`git rev-list --all --max-parents=0`
for root in $roots; do
        git log --all --ancestry-path ^$root --pretty=%D \
        | awk 1 RS='\n+|, | -> ' >tips-$root
done

这是问题中与Git相关的部分,剩下的是要从这些集合中识别不相交的图形。任意两个提示集中的公共元素将连接这些图形。

A--\     tools
*---B    master
C--/     doc-html

有三个提示,toolsdoc-html没有共同的根,但它们各自的图形都连接到master提示,如果你看整个东西,这里只有一个连接的DAG。 sort tips-*|uniq -c|sort -n|tail -1会告诉您任何一个提示加入的最大根数,echo $roots|wc -w将告诉您有多少根,如果它们匹配,则拥有一个连接历史记录,如果不匹配,则还有待完成的工作。

在任何工业规模上,我都会研究一下关于识别不相交集合的图论,但逐步合并一系列暂时不相交的集合看起来足够高效了,这在此情况下意味着“可能是全部内容”,并且在基本的Unix工具范围内。对于真正的一次性任务,甚至不需要awk,只需使用带有shell数组跟踪集合的普通旧shell脚本即可。isdisjoint() { return $(( 0 == `sort $*|uniq -d|wc -l` )); }等等。


1
据我所知,Git不会跟踪单个DAG根节点。以下是我想到的一种伪代码方法来查找它们。
# Get a list of all branches.
branches = `git branch`

# Store an empty list of roots.
roots = []

while branches
  # Pick a branch, any branch.
  branch = branches.pop

  # Find its root and add it to the list.
  root = `git log --topo-order --oneline #{branch} | tail -1`
  roots << root

  # Remove any branches which contain the root.
  branches -= `git branch --contains #{root}`
end

p roots

3
git rev-list --all --max-parents=0 可以找到所有的根节点。git log --pretty=%D --ancestry-path --all ^$root 可以找到追溯到任何一个特定根节点的所有引用。 - jthill
@jthill 很好!那应该是一个更好的答案。 - Schwern
一个分支可能有多个根,这使得这种解决方案有点低效。 - torek

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