マージ戦略とスカッシュ マージ
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
pull request が完了したら、トピック ブランチを既定のブランチ (通常は main
) にマージします。 このマージにより、トピック ブランチのコミットがメイン ブランチに追加され、既定のブランチとトピック ブランチ間の競合を調整するためのマージ コミットが作成されます。 pull request のコメントとディスカッションは、トピック ブランチで行われた変更に関する追加のコンテキストを提供します。
main
ブランチ (またはその他の既定のブランチ) のコミット履歴は、関連するトピック ブランチ履歴により、直線をフォローしません。 プロジェクトが大きくなるにつれて、同時に作業したトピック ブランチの数が増えるため、既定のブランチ履歴をフォローするのがますます難しくなります。
既定のブランチは各トピック ブランチの履歴を正確に表していますが、プロジェクトの開発に関するより広範な質問に答えるために使用するのは困難です。
スカッシュ マージ
スカッシュ マージはマージ オプションの 1 つであり、pull request を完了したときにトピック ブランチの Git 履歴をまとめることができます。 トピック ブランチの各コミットを既定ブランチの履歴に追加する代わりに、スカッシュ マージでは、既定ブランチの新しい単一のコミットにすべてのファイルの変更を追加します。 スカッシュ マージ コミットにはトピック ブランチへの参照がなく、トピック ブランチからのすべての変更を含む新しいコミットが生成されます。 さらに、混乱を防ぐためにトピック ブランチを削除することをお勧めします。
簡単に考えると、スカッシュ マージではファイルの変更のみを提供し、通常のマージではファイルの変更とコミット履歴が提供されます。
スカッシュ マージはどのように役立ちますか?
スカッシュマージでは、チームにワークフローの変更を要求することなく、既定のブランチ履歴をクリーンでフォローしやすい状態に維持します。 トピック ブランチの共同作成者は、トピック ブランチで必要な作業を行い、既定のブランチでは、スカッシュ マージを使用して線形履歴を維持します。 スカッシュ マージで更新された main
ブランチのコミット履歴には、マージされたブランチごとに 1 つのコミットが含まれます。 この履歴をたどることで、作業が完了したタイミングを正確に確認できます。
スカッシュ マージの実施時の考慮事項
スカッシュ マージでは、既定のブランチの変更履歴がまとめられるため、チームと協力して、スカッシュ マージすべきタイミングや、トピック ブランチの完全なコミット履歴を保持するタイミングを判断することが重要です。 スカッシュ マージする場合は、ソース ブランチを削除することをお勧めします。 ソース ブランチを削除すると、トピック ブランチ自体に既定のブランチにマージするコミットが含まれないため、混乱を防ぐことができます。
スカッシュ マージを使用して pull request を完了する
Azure Repos で pull request を完了する際にスカッシュ マージを選択することができます。
[Pull Request の完了] ダイアログで [マージの種類] の下にある [スカッシュ コミット] を選択して、トピック ブランチをスカッシュ マージします。
複数のマージ ベース
pull request の [ファイル] タブでは、3 面比較によって差分を検出します。 このアルゴリズムでは、ターゲット ブランチの最後のコミット、ソース ブランチの最後のコミット、および共通のマージ ベース (つまり、最も一般的な祖先) が考慮されています。 このアルゴリズムは、変更を検出する高速でコスト効率の高い信頼できる方法です。 残念ながら、真のベースが複数ある場合もあります。 ほとんどのリポジトリでは、この状況はまれですが、アクティブなユーザーが多い大規模なリポジトリでは、頻繁に発生する可能性があります。 ブランチ間に複数のマージ ベースが存在するかについて手動で確認できます。 これを行うには、git merge-base --all feature master
コマンドを実行します。 Azure DevOps は、PR ごとに複数のマージ ベースが存在することを検出します。 これが検出されると、Azure DevOps に「複数のマージ ベースが検出されました」というメッセージが表示されます。 表示されるコミットの一覧は、PR で完全ではないことがあります。 Azure DevOps では複数のマージ ベースの検出が実行されますが、マージ ベースの可能性が既にマージされているかは確認されません。 このような確認は git merge-base
によって行われます。 このため、Azure DevOps は、git merge-base
が 1 つのマージ ベースのみをレポートする場合でもメッセージを表示することがあります。
Note
PR レビュー中に変更が失われた場合は、複数のマージ ベースが根本原因ではないことを確認してください。
次のシナリオは、Azure DevOps によって複数のベースとして検出されます (マージ ベースは番号 1と 2 で示されます)。
- 異なるブランチ間のクロス マージ (クリス クロスとも呼ばれる) (Azure DevOps および
git merge-base
によって報告されます)
---1---o---A
\ /
X
/ \
---2---o---o---B
- 1 つのブランチを他の 2 つにマージ (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
- 機能ブランチのアクティブな再利用
- 復元、チェリーピック、マージを使用した、直感的でない複雑な他の操作
複数のマージ ベースの検出は、セキュリティ認識の一部です。 複数のマージ ベースがある場合、選択したマージ ベースによっては、ユーザー インターフェイスのファイル diff アルゴリズムでファイルの変更が正しく検出されない可能性があります。 pull request のファイルのバージョンがマージ ベース間で異なる場合、複数のマージ ベースの警告が発生します。
詳細については、公式の git ドキュメントを参照してください。
複数のベースからマージする潜在的なセキュリティ リスク
- 悪意のあるユーザーが UI アルゴリズムを悪用して、PR に存在しない悪意のある変更をコミットする可能性があります。
- PR で提案された変更が既にターゲット ブランチにある場合、[ファイル] タブに表示されますが、フォルダーの変更にマップされるブランチ ポリシーはトリガーされない可能性があります。
- 複数のマージ ベースから同じファイルに対して行われた 2 セットの変更が PR に存在しない場合があります。 その場合、危険なロジック ギャップが発生する可能性があります。
複数のマージ ベースの問題を解決する方法
複数のマージ ベースを持つことは必ずしも悪いわけではありませんが、すべて問題ないことをダブルチェックする必要があります。 複数のマージ ベースを取り除くには、ターゲットでブランチをリベースするか、ターゲットをブランチにマージすることで、ブランチを共通する単一の祖先に結び付けます。 これらのアクションは警告メッセージを取り除き、実際の変更が問題ないかどうかをチェックするのに役立ちます。
1 つは、リベースまたはマージする前に、ソフト リセットして進行状況をスタッシュする方法です。 その後、新しいブランチを作成したり、空のブランチをリベースして、明確な点から変更を適用したりすることができます。 変更が既に存在する場合、このプロセスではリモートに強制プッシュする必要がある場合があります。
複数のマージ ベースの問題を防止する方法
ここでは、複数のマージ ベースの問題を防止するための一般的なヒントについて説明します。
- pull request を準備するときは、メインまたはリリース ブランチの最新バージョンから機能ブランチを作成します。
- 必要な場合を除き、リポジトリの安定したブランチから直接発生していないブランチを作成しないでください。
複数のマージ ベースの問題が再び表示された場合の対応
多くのアクティブな共同作成者を持つ大規模なリポジトリでは、この問題は特に不便になるでしょう。 マージを使用して複数のベースを取り除いても、その状況が再発する場合があります。 ユーザーの誰かが長期間続いていた pull request を閉じても、その状況が再現される可能性があります。 ビルド ポリシーを使用しており、テストが実行中であっても、pull request を完了する手段はありません。 リセットして新しいブランチを開始すると、解決するかもしれません。 変化がなければ、その状況が繰り返されても、ご自身の変更は明確にわかるでしょう。