![](/img/trans.png)
[英]How to get list of all branches created off a GIT branch (get all sub branches of a branch)
[英]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>
。
但是,上述方法存在一些问题:
git branch --contains
命令范围内的每个哈希。 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
。 (如果你使用--reverse
和head -1
你可以得到一个破管失败,所以tail -1
方法更好。令人讨厌的是,你不能将--reverse
与-n 1
结合起来。)
您可能会担心这种情况会出现故障:
o--o <-- master
/
...--o--o--1--o--o <-- branch-X
\ \
2--*--* <-- develop
\
o <-- branch-Y
您可能希望包含branch-X
和branch-Y
,并且不会通过使用单个git branch --contains
操作找到它们,因为它们是master..develop
范围中两个不同提交的后代,在此表示为1
和2
。 在这里,你真的需要多个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.