Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-merge-tree 上次更新於 2.46.0

名稱

git-merge-tree - 執行合併,不觸及索引或工作目錄

概要

git merge-tree [--write-tree] [<options>] <branch1> <branch2>
git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2> (deprecated)

描述

此命令具有現代的 --write-tree 模式和已棄用的 --trivial-merge 模式。除了結尾的 已棄用描述 區段外,本文件其餘部分都描述現代的 --write-tree 模式。

執行合併,但不建立任何新的提交,也不讀取或寫入工作目錄或索引。

執行的合併將使用與「真實」git-merge[1] 相同的功能,包括

  • 個別檔案的三向內容合併

  • 重新命名偵測

  • 正確的目錄/檔案衝突處理

  • 遞迴祖先合併(即,當有多個合併基準時,透過合併合併基準來建立虛擬合併基準)

  • 等等。

合併完成後,會建立新的最上層樹狀物件。請參閱下方的 OUTPUT 以了解詳細資訊。

選項

-z

不要在 區段中引用檔案名稱,並以 NUL 字元而非換行符號結束每個檔案名稱。同時以 NUL 字元而非換行符號開始訊息區段。請參閱下方的 OUTPUT 以了解更多資訊。

--name-only

在「衝突檔案資訊」區段中,不要寫出 (模式、oid、階段、路徑) 元組的清單到有衝突檔案的輸出中,僅提供衝突檔案的檔案名稱清單(如果有多個衝突階段,則不要多次列出檔案名稱)。

--[no-]messages

將任何資訊訊息(例如「自動合併 <路徑>」或衝突通知)寫入 stdout 的結尾。如果未指定,則預設行為是在有合併衝突時包含這些訊息,否則省略它們。

--allow-unrelated-histories

如果指定的兩個分支沒有共同的歷史記錄,merge-tree 預設會錯誤結束。可以提供此旗標來覆蓋該檢查,並讓合併繼續進行。

--merge-base=<tree-ish>

不要尋找 <branch1> 和 <branch2> 的合併基準,而是指定合併的合併基準,目前不支援指定多個基準。此選項與 --stdin 不相容。

由於直接提供合併基準,<branch1> 和 <branch2> 不需要指定提交;樹狀結構就足夠了。

-X<option>
--strategy-option=<option>

將合併策略特定的選項傳遞給合併策略。請參閱 git-merge[1] 以了解詳細資訊。

輸出

對於成功的合併,git-merge-tree 的輸出僅為一行

<OID of toplevel tree>

而對於衝突的合併,預設的輸出格式為

<OID of toplevel tree>
<Conflicted file info>
<Informational messages>

這些將在下面單獨討論。

但是,有一個例外。如果傳遞了 --stdin,則開頭會有一個額外的區段,結尾會有一個 NUL 字元,然後所有區段都會針對輸入的每一行重複。因此,如果第一次合併發生衝突,第二次合併是乾淨的,則輸出格式將為

<Merge status>
<OID of toplevel tree>
<Conflicted file info>
<Informational messages>
NUL
<Merge status>
<OID of toplevel tree>
NUL

合併狀態

這是一個整數狀態,後接一個 NUL 字元。整數狀態為

   0: merge had conflicts
   1: merge was clean
   <0: something prevented the merge from running (e.g. access to repository
objects denied by filesystem)

最上層樹狀結構的 OID

這是一個樹狀物件,表示在 git merge 結束時,工作目錄中會簽出什麼。如果有衝突,則此樹狀結構中的檔案可能會嵌入衝突標記。此區段後面總是跟著換行符號(如果傳遞了 -z,則為 NUL)。

衝突檔案資訊

這是一系列的行,格式如下

<mode> <object> <stage> <filename>

檔案名稱將會如同 core.quotePath 配置變數所解釋的那樣引用(請參閱 git-config[1])。但是,如果傳遞了 --name-only 選項,則會省略模式、物件和階段。如果傳遞了 -z,則「行」將以 NUL 字元而非換行符號終止。

資訊訊息

此區段提供資訊訊息,通常是有關衝突的資訊。此區段的格式會隨著是否傳遞了 -z 而有顯著差異。

如果傳遞了 -z

輸出格式為零個或多個衝突資訊記錄,每個記錄的格式為

<list-of-paths><conflict-type>NUL<conflict-message>NUL

其中 <list-of-paths> 的格式為

<number-of-paths>NUL<path1>NUL<path2>NUL...<pathN>NUL

並包含 <conflict-message> 中受衝突或資訊訊息影響的路徑(或分支名稱)。此外,<conflict-type> 是一個穩定的字串,用於解釋衝突的類型,例如

  • 「自動合併」

  • 「衝突(重新命名/刪除)」

  • 「衝突(子模組缺少合併基準)」

  • 「衝突(二進位)」

而 <conflict-message> 是一個關於衝突的更詳細訊息,通常(但並非總是)在其中嵌入 <stable-short-type-description>。這些字串在未來的 Git 版本中可能會變更。一些範例

  • 「自動合併 <檔案>」

  • 「衝突(重新命名/刪除):<舊檔案> 已重新命名…​但在…​中已刪除」

  • 「合併子模組 <子模組> 失敗(沒有合併基準)」

  • 「警告:無法合併二進位檔案:<檔案名稱>」

如果未傳遞 -z

此區段以空白行開始,以將其與前一個區段分隔開來,然後僅包含上一個區段中的 <conflict-message> 資訊(以換行符號分隔)。這些是非穩定的字串,不應由腳本剖析,僅供人類使用。此外,請注意,雖然 <conflict-message> 字串通常不包含嵌入的換行符號,但有時確實會包含。(但是,自由格式的訊息永遠不會有嵌入的 NUL 字元)。因此,整塊資訊是作為所有衝突訊息的集合,供人類讀取。

結束狀態

對於成功的非衝突合併,結束狀態為 0。當合併有衝突時,結束狀態為 1。如果合併由於某種錯誤而無法完成(或開始),則結束狀態為 0 或 1 以外的值(且輸出未指定)。當傳遞 --stdin 時,成功和衝突的合併的傳回狀態均為 0,如果無法完成所有請求的合併,則傳回狀態為 0 或 1 以外的值。

使用注意事項

此命令的目的是作為低階工具,類似於 git-hash-object[1]git-mktree[1]git-commit-tree[1]git-write-tree[1]git-update-ref[1]git-mktag[1]。因此,它可以作為一系列步驟的一部分,例如

NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2)
test $? -eq 0 || die "There were conflicts..."
NEWCOMMIT=$(git commit-tree $NEWTREE -p $BRANCH1 -p $BRANCH2)
git update-ref $BRANCH1 $NEWCOMMIT

請注意,當結束狀態為非零時,此序列中的 NEWTREE 將包含比僅僅一個樹狀結構更多的輸出。

對於衝突,輸出包含與使用 git-merge[1] 相同的資訊

輸入格式

git merge-tree --stdin 輸入格式完全基於文字。每一行的格式如下

[<base-commit> -- ]<branch1> <branch2>

如果一行以 -- 分隔,則分隔符號之前的字串用於指定合併的合併基準,而分隔符號之後的字串描述要合併的分支。

要避免的錯誤

不要查看產生的最上層樹狀結構來嘗試找出哪些檔案發生衝突;請改為剖析 衝突檔案資訊 區段。在大型儲存庫中剖析整個樹狀結構不僅會非常慢,而且還有許多類型的衝突無法用衝突標記表示(修改/刪除、模式衝突、兩邊都已變更的二進位檔案、檔案/目錄衝突、各種重新命名衝突排列等等)。

不要將空的 衝突檔案資訊 清單解讀為乾淨的合併;請檢查結束狀態。合併可能會發生衝突,而沒有個別檔案發生衝突(有一些目錄重新命名衝突類型屬於此類別,將來也可能會新增其他類型)。

請勿嘗試從衝突檔案資訊列表去猜測或讓使用者猜測衝突類型。該處的資訊不足以做到這一點。例如:重新命名/重新命名 (1對2) 的衝突(雙方以不同的方式重新命名同一個檔案)將會導致三個不同的檔案具有較高的階段(但每個檔案只有一個較高的階段),而且沒有辦法(除了資訊訊息區段)判斷哪三個檔案是相關的。檔案/目錄衝突也會導致一個檔案只有一個較高的階段。可能涉及目錄重新命名的衝突(當 "merge.directoryRenames" 未設定或設定為 "conflicts" 時)也會導致一個檔案只有一個較高的階段。在所有情況下,資訊訊息區段都有必要的資訊,儘管它並非設計為可供機器解析的。

請勿假設衝突檔案資訊中的每個路徑,與資訊訊息中的邏輯衝突之間存在一對一的對應關係,也不要假設存在一對多或多對一的對應關係。存在多對多的對應關係,這表示每個路徑在單次合併中可能有多種邏輯衝突類型,而且每個邏輯衝突類型可能會影響多個路徑。

請勿假設資訊訊息區段中列出的所有檔案名稱都有衝突。訊息可能包含沒有衝突的檔案,例如 "自動合併 <檔案>"。

請避免從衝突檔案資訊中取得 OID 並重新合併它們,以向使用者呈現衝突。這將會遺失資訊。相反地,請查詢在頂層樹的 OID中找到的檔案版本,並顯示該版本。特別是後者將具有以正在合併的原始分支/提交來標註的衝突標記,如果涉及重新命名,則會包含原始檔案名稱。雖然您可以在重新合併時將原始分支/提交包含在衝突標記註解中,但無法從衝突檔案資訊中取得原始檔案名稱,因此您將會遺失可能幫助使用者解決衝突的資訊。

已棄用的說明

根據說明,且與本文件其他部分不同,本節描述的是已棄用的 --trivial-merge 模式。

除了可選的 --trivial-merge 之外,此模式不接受任何選項。

此模式讀取三個樹狀物件 (tree-ish),並以半差異格式將簡易合併結果和衝突階段輸出到標準輸出。由於這是設計給較高層級的腳本使用,以將結果合併回索引,因此它會省略與 <branch1> 相符的條目。第二種形式的結果類似於三向 *git read-tree -m* 所做的,但指令不是將結果儲存在索引中,而是將條目輸出到標準輸出。

此形式不僅適用性有限(簡易合併無法處理個別檔案的內容合併、重新命名偵測、正確的目錄/檔案衝突處理等),而且輸出格式也很難處理,即使在合併成功的情況下,其效能通常也會低於第一種形式(尤其是在大型儲存庫中工作時)。

GIT

屬於 git[1] 套件的一部分

scroll-to-top