Azure DevOps のプルリクのマージ競合
Azure Repos のプルリクエストで、ソース ブランチとターゲット ブランチが同じ行を別々に変えていたり、片方が変えたファイルをもう片方が消していたりすると、Azure DevOps はマージ コミットを作れず、プルリクは「競合」で止まります。以下は、そのとき何が出て、どうすればプルリクが先へ進むかを、Microsoft の pull request を完了、破棄、または元に戻す・Git のマージ競合を解決する・Pull Requests - Get(英語)からまとめたものです。
Azure DevOps に出るもの
- 競合しているファイルは、プルリクの概要(Overview)ページに並びます。
- 完了も自動完了も待ちになる:競合を解消するまで、プルリクはマージできず、自動完了にも設定できません。すでに自動完了にしてあるプルリクは、競合で完了できないとメールで知らせます。
- マージの下見:概要の右上の More options > View merge changes で、Azure DevOps が作るはずのマージ コミットが見られます。プルリクのターゲット ブランチを変えたあとは、Restart merge で下見のマージを作り直します。
- 自分で試し直す:Azure DevOps はソース ブランチが変わるたびにマージをやり直します。つまり、解消したものをソース ブランチにプッシュすれば競合は消えます。
手元で解消する
ふつうは、手元でターゲット ブランチをソース ブランチにマージし、そこで競合を解消してプッシュします。ソース ブランチが feature、ターゲットが main なら:
git fetch origin
git checkout feature
git merge origin/main
# Git は "Automatic merge failed; fix conflicts and then commit the result." で止まる
# 競合したファイルを直してから
git add <ファイル> # 片方で消されたファイルを消すなら git rm <ファイル>
git merge --continue
git push
git statusで競合したファイルが、git log --mergeで競合しているコミットが分かります。git merge --abortで始める前に戻ります。- 競合したファイルの中では、
<<<<<<<と=======の間が今いるブランチの内容、=======と>>>>>>>の間が取り込んだブランチの内容です。印を消すと、解消したことになります。 - マージの代わりに、ソース ブランチをターゲットの上にリベースしてプッシュすることもできます。ブランチのコミットが書き換わるので、プッシュは置き換え(
git push --force-with-lease)になり、そのブランチの Force push の権限が要ります。 - マージが触るファイルにコミットしていない変更があると止まります("Your local changes to the following files would be overwritten by merge")。先にコミットするか stash してください。
ブラウザーで解消する
Web の画面は競合を並べるだけで、直す編集画面はありません。Microsoft DevLabs の Pull Request Merge Conflict Extension を Visual Studio Marketplace から組織に入れると、プルリクに Conflicts タブが増え、ファイルを選んで解消のしかたを決め、VS Code の編集部品(Monaco)で直して送れます。掲載ページには既知の問題として、8 MB を超えるファイルはソースかターゲットのファイルを丸ごと取ることしかできない場合があること、競合が見つかったファイルしか編集できないこと、ディレクトリとファイルの競合には対応していないこと、競合したファイルの更新が Files タブに出ないことが書かれています。DevLabs は、自分の拡張機能を「サポート対象外の実験」と説明しています。また、この拡張機能で解消したプルリクは、リベースのマージの種類では完了できません。Microsoft は、3方向マージに当てた解消は、コミットを1つずつリベースし直すとまず有効にならないと説明しています。手元でリベースしてプッシュするか、スカッシュにします。
REST API から
GET …/_apis/git/repositories/{repositoryId}/pullrequests/{pullRequestId}のmergeStatusがプルリクのマージの状態です:conflicts(競合でマージに失敗)・succeeded・queued・rejectedByPolicy・failure・notSet。lastMergeCommitは直近のマージのコミットで、空ならそのマージは実行中か、うまくいかなかったものです。lastMergeSourceCommitとlastMergeTargetCommitは、そのマージの元になった両ブランチの先頭です。- ほかの理由でマージに失敗すると
mergeFailureMessageが入り、mergeFailureTypeがcaseSensitive(大文字・小文字の食い違い)やobjectTooLargeを示すことがあります。
IntelliJ IDEA でマージ競合を解消する
Azure DevOps Pull Requests は、Lesstep が作っている JetBrains IDE(2024.1 以降)と Android Studio のプラグインです。Azure DevOps Services と Azure DevOps Server のプルリクエストを IDE のツールウィンドウに並べます。1.0.57 から、マージ競合のあるプルリクは概要のいちばん上にそう出て、IDE で解消するを押すと、fetch してソース ブランチをチェックアウトし、ターゲット ブランチをそこへマージします。競合したファイルは IDE のマージの画面(自分の変更を採用・相手の変更を採用・左右に並べてマージ)で開きます。1.0.60 からは、概要に競合しているファイルと、それぞれ何がぶつかっているか(両方で変更・片方で削除・両方で追加・別々に名前を変更・ファイルとフォルダー)を、Azure DevOps がそのプルリクについて返すとおりに先に並べます。マージをコミットしてブランチをプッシュすれば、Azure DevOps がマージを試し直します。競合の解消は無料で、レビューの受信箱・差分・ブランチ ポリシーも無料、投票・コメント・完了・プルリクの作成は Pro(30日間の無料試用つき)です。画面は日本語です。
Azure DevOps は Microsoft Corporation の商標、IntelliJ IDEA は JetBrains s.r.o. の商標です。このページは Microsoft・JetBrains のいずれとも提携しておらず、承認も受けていません。
ほかに:自動完了と任意のポリシー · マージの種類 · ビルドの検証 · English