簡體   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