繁体   English   中英

Git:如何列出从特定分支创建的所有分支?

[英]Git: How to list all branches that were created from a specific branch?

我需要生成与创建的所有分支名称的报告develop分支(这是分支master在过去的某个时候)。 我的方法是让第一个和最后犯develop利用git log --pretty=format:"%h" master..develop ,然后使用提交的范围与git branch --contains <hash>

但是,上述方法存在一些问题:

  1. 我需要运行命令来了解我的查询中要考虑的提交范围。
  2. 我将不得不重复git branch --contains命令范围内的每个哈希。
  3. git branch --contains命令的输出在大多数情况下都会包含冗余结果,因为大多数提交在分支之间是通用的。

我希望有更好,更直接的方式来做到这一点。 下面我将尝试说明感兴趣的案例:

  master
    ^
    |                      develop
a---b                        ^
     \                       |
      --c--d---e---f---g--h--i
           \      \    \      \
            k-l    m    n      o--p
              ^    ^    ^         ^
              |    |    |         |
         branch_1  | branch_3     |
                 branch_2       branch_4

// Desired output:
branch_1
branch_2
branch_3
branch_4

你可以用一个命令非常接近:

git log --ancestry-path  --branches --not $(git merge-base --all master develop) \
        --pretty=%D  --simplify-by-decoration --decorate-refs=refs/heads

这是“向我展示所有分支历史中的分支装饰,追溯到当前合并基础的大师和开发”。

你可以通过awk '{print $NF}' RS=', |\\n'类的方式将结果输出来更漂亮。

请注意,这(就像@ torek的答案)假设你在一个为你的生产大师管理档案级稳定性的仓库中做这件事,根本没有必要的分支名称和提交之间的关系,更不用说永久性,全球性或独特性一。 如果您尝试永久地将提交绑定到某些外部管理记录,请在提交消息中执行,而不是分支名称。

编辑:如果您想快速了解自master-develop拆分后的当前分支结构,

git log --graph --decorate-refs=refs/heads --oneline \
         --branches --simplify-by-decoration \
         --ancestry-path --boundary --not `git merge-base master develop`

分支名称只指向一个提交。 通过从该点向后遍历图表,可以找到属于该分支的所有早期提交。 这就是master..develop部分的工作原理,例如:它选择了作为develop祖先的提交,排除了作为master祖先的任何提交。

(请注意,例如,在这种情况下:

          o--o   <-- master
         /
...--o--o
         \
          *--*--*   <-- develop

双点master..develop语法包括三个已提交的提交。)

我想你在这里要求的是:

for each branch name $branch:
    if $branch identifies a commit that is a descendant of any
               of the commits in the set `master..develop`:
        print $branch

但是,任何提交,例如,提交i的后代,根据定义是提交c的后代。 所以,正如tkruse在评论中所说

git branch --contains <hash-of-c>

应该足够了。 要查找此处使用的提交,您可以运行git rev-list --topo-order master..develop | tail -1 git rev-list --topo-order master..develop | tail -1 (如果你使用--reversehead -1你可以得到一个破管失败,所以tail -1方法更好。令人讨厌的是,你不能将--reverse-n 1结合起来。)

您可能会担心这种情况会出现故障:

          o--o   <-- master
         /
...--o--o--1--o--o   <-- branch-X
         \  \
          2--*--*   <-- develop
           \
            o   <-- branch-Y

您可能希望包含branch-Xbranch-Y ,并且不会通过使用单个git branch --contains操作找到它们,因为它们是master..develop范围中两个不同提交的后代,在此表示为12 在这里,你真的需要多个git branch --contains -es,或者:

set -- $(git rev-list master..develop)
git for-each-ref --format='%(refname)' refs/heads | while read ref; do
    branch=${ref#refs/heads/}
    tip=$(git rev-parse $ref)
    take=false
    for i do
        if git merge-base --is-ancestor $i $tip; then
            take=true
            break
        fi
    done
    $take && echo $branch
done

(未经测试,至少有一个错误到目前为止)。 但这比简单的git branch --contains测试慢得多。 这里的逻辑是确定rev-list输出中的任何提交散列ID是否是所讨论的分支的尖端的祖先。

(注意,这将打印develop - git merge-base --is-ancestor认为提交是它自己的祖先 - 所以你可能想要显式跳过那个。)

(你可以找到公正适当的基础提交。在上面的例子,例如,只有两个。然后,您可以使用加快这很多--contains那些和工会指定的分支机构。使用碱基数任何合并的数量和结构的函数犯master..develop它可能会使用。 git rev-list --boundary找到刚才边界提交;我没有这个实验)

附录

我在午餐时意识到,有一种简单的方法可以找到--contains--contains --is-ancestor测试的最小提交。 从范围中的完整提交列表开始,首先按照父项的拓扑顺序排序,例如:

set -- $(git rev-list --reverse --topo-order master..develop)

然后从一个空的“我们必须检查的提交”列表开始:

hashes=

现在,对于所有可能哈希值列表中的每个哈希ID,测试每个哈希值,例如:

if ! is_descendant $i $hashes; then
    hashes="$hashes $i"
fi

其中is_descendant是:

# return true (i.e., 0) if $1 is a descendant of any of
# $2, $3, ..., $n
is_descendant() {
    local i c=$1
    shift
    for i do
        # $i \ancestor $c => $c \descendant $i
        git merge-base --is-ancestor $i $commit_to_test && return 0
    done
    return 1
}

循环完成后, $hashes包含可用于--contains--contains --is-ancestor测试的最小提交集。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM