[英]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.