共用方式為


合併策略和壓縮合併

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

當您完成 拉取請求時,您會將主題分支合併至您的預設分支,通常為 main。 此合併會將主題分支的提交新增至主要分支,並建立合併提交來協調預設與主題分支之間的任何衝突。 提取要求中的批注和討論為主題分支中所做的變更提供更多內容。

pull request 中的常規合併範例。

提交的歷史在您的main分支(或其他預設分支)因相關主題分支的歷史影響而不呈直線。 當專案變大時,同時處理的主題分支數目會增加,使得預設分支歷程記錄越來越難以遵循。

預設分支準確地表示每個主題分支的歷程記錄,但很難用來回答有關專案開發中更廣泛的問題。

先決條件

類別 需求
專案存取 專案的成員。
許可 - 在私人項目中檢視程式碼:至少 基本 權限。
- 複製或貢獻私人專案中的程式碼:作為 貢獻者 安全群組的成員或在專案中具有相應的許可權。
- 設定分支或存放庫許可權:管理分支或存放庫的許可權 許可權。
- 變更預設分支:編輯原則 存放庫的許可權。
- 匯入存放庫:專案管理員成員 安全組或 Git 專案層級 建立存放庫 許可權設定為 允許。 如需詳細資訊,請參閱 設定 Git 存放庫許可權
服務 已啟用 Repos
工具 選擇性。 使用 az repos 命令:Azure DevOps CLI

備註

在公用專案中,具有 項目關係人 存取權的使用者具有 Azure Repos 的完整存取權,包括檢視、複製及參與程式代碼。

類別 需求
專案存取 專案的成員。
許可 - 查看程式碼:至少 基本 權限。
- 複製程式碼或貢獻程式碼:屬於 參與者安全組 的成員或具有專案中的對應許可權。
服務 已啟用 Repos

合併壓縮

Squash 合併是一個合併選項,可讓您在完成提取要求時壓縮主題分支的 Git 歷程記錄。 與其將主題分支上的每個提交新增到預設分支的歷程記錄中,squash merge 會將所有檔案變更合併成預設分支上的單一新提交。 Squash 合併提交沒有議題分支的參考。 它會產生一個新的 提交,其中包含主題分支的所有變更。 建議您刪除主題分支,以避免發生任何混淆。

Azure Repos 中拉取請求的合併壓縮圖表。

一個簡單的思考方式是,壓縮合併只給您提供檔案變更,而一般合併會提供檔案變更和提交歷史記錄。

squash merge 如何有幫助?

Squash 合併會讓您的預設分支歷程記錄保持乾淨且易於遵循,而不需要對小組進行任何工作流程變更。 主題分支的貢獻者可以根據自己的方式在主題分支中工作,而預設分支則使用「squash merge」以保持線性歷史記錄。 使用 squash merge 更新的 main 分支的提交歷程記錄,每個合併後的分支都有一個提交。 您可以瀏覽此歷程記錄,以確切找出工作完成的時間。

壁球合併時的考慮

Squash 合併 (壓縮合併) 會壓縮預設分支中變更的歷史記錄,因此您應與小組合作,決定何時應該採用壓縮合併,而不是保留議題分支的完整提交歷史記錄。 當進行壓縮合併時,最好刪除來源分支。 刪除來源分支可防止混淆,因為主題分支本身沒有將它合併至預設分支的認可。

使用 squash merge 完成提取要求

在 Azure Repos 中完成拉取請求時,您可以選擇壓縮合併。

在 [完成提取要求 ] 對話方塊的 [完成提取要求] 對話框中,選擇 [合併 類型] 底下的 [Squash 認可] 來壓縮主題分支。

Azure Repos 中使用 Squash 合併關閉提取請求的螢幕截圖。

多個合併基底

提取要求中的 [檔案] 索引標籤會透過三端比較來偵測差異。 此演算法會考慮目標分支中的最後一次提交、來源分支中的最後一次提交,以及其 共同合併基礎,例如,最佳常見祖先。 此演算法是偵測變更的快速、符合成本效益且可靠的方法。 不幸的是,在某些情況下,有一個以上的真實基礎。 在大部分的存放庫中,這種情況很少見,但在具有許多作用中使用者的大型存放庫中,可能很常見。 您可以手動檢查分支之間的多個合併基底是否存在。 若要這樣做,請執行 git merge-base --all feature master 命令。 Azure DevOps 會偵測每個 PR 有多個合併基底存在。 偵測到這些專案時,Azure DevOps 會顯示「偵測到多個合併基底」訊息。 PR 顯示的提交清單可能不完整。 雖然 Azure DevOps 正在執行多個合併基底的偵測,但不會檢查潛在的合併基底是否已合併。 這類檢查是由 git merge-base完成。 這就是為什麼即使 git merge-base 只報告一個合併基底,Azure DevOps 仍可能會顯示訊息。

備註

如果您在PR檢閱期間遺失變更,請確定多個合併基底不是根本原因。

下列範例情境會由 Azure DevOps 偵測出多個合併基底,並以數字一和二表示的合併基底:

  • 不同分支之間的交叉合併(也稱為 criss-cross)(由 Azure DevOps 和 git merge-base所報告)
---1---o---A
    \ /
     X
    / \
---2---o---o---B
  • 將一個分支合併至另外兩個分支(由 Azure DevOps 回報,但不是由排除合併基底 2 的 git merge-base 所報告)
---1---o---o---o---A
    \         /
     \-------2
      \       \
       \---o---o---o---B
  • 處理主要分支還原後的結果,例如,修改合併提交
*   42bb2d2 (HEAD, A) Amended merge commit
|\  
| | *   67c9bb8 (other) Merge branch 'A' into B
| | |\  
| |/ /  
|/| /   
| |/    
| * fa78e32 add second commit
* | 15845c9 add first commit
|/  
* 6a52130 add init
  • 主動重複使用功能分支
  • 其他不直觀且複雜的還原、挑選和合併操作

多重合併基底偵測是安全性感知的一部分。 如果有多個合併基底,使用者介面的檔案差異演算法可能無法正確偵測檔案變更,視它選擇的合併基底而定。 如果提取要求中的檔案在合併基底之間有不同的版本,就會發生多個合併基底警告。

如需詳細資訊,請檢閱 官方 git 檔

從多個基底合併的潛在安全性風險

  • 惡意使用者可能會濫用 UI 演算法來進行於 PR 中不存在的惡意變更。
  • 如果 PR 中提議的變更已經在目標分支中,它們會顯示在 [檔案] 索引標籤中,但可能不會觸發映射到資料夾變更的分支策略。
  • 來自多個合併基底之相同檔案的兩組變更可能不會出現在PR中。 這種情況可能會造成危險的邏輯差距。

如何解決多個合併基底問題

有多個合併基底不一定不好,但您應該仔細檢查一切是否正常。 若要擺脫多個合併基底,請將分支系結至單一通用上階,方法是將分支重新放入目標上,或將目標合併至您的分支。 這些動作會清除警告訊息,並協助您檢查實際變更是否正常。

在重置或合併之前,先將進度暫存。 然後,您可以建立新的分支或將一個空白分支重新基礎化,並從明確的起點套用您的變更。 如果您的變更已經上傳,此過程可能需要強制推送到遠端。

如何避免多個合併基底問題

以下是避免多個合併基底問題的一般秘訣:

  • 準備提取要求時,請從最新版的主要或發行分支建立功能分支。
  • 除非必要,否則請避免建立不直接源自存放庫穩定分支的分支。

如果多個合併基底問題再次出現,該怎麼辦

在有許多活躍貢獻者的大型倉庫中,此問題可能特別麻煩。 即使您透過合併消除多個基底,這種情況仍可能再次發生。 如果有人關閉長期拉取請求,就可能重新出現這種情況。 即使建置原則和測試正在執行,您也沒有任何方法可以完成提取要求。 重置並啟動一個新分支可能會有幫助。 如果沒有進行任何變更,即使情況重複,您的變更可能也很清楚。

後續步驟