GitHubで開発を進める上で、プルリクエストは欠かせない機能です。しかし、複数のPRが同じ変更内容を含んでいた場合に、予期せぬ挙動があったのでメモに残したいと思います。今回同一内容のプルリクエストのマージに関する挙動とその注意点について解説します。
質問 同一の内容のプルリクエストの片方をマージしたらどうなるのか?
例えば、メインブランチから派生したブランチ1とブランチ2があり、それぞれから同じ変更内容を含むPR(プルリクエスト1とプルリクエスト2)が作成されたとします。
もし、この状況でプルリクエスト1をマージするとどうなるでしょうか?
解答 プルリクエスト2も「マージ済み」として扱われる!
プルリクエスト1がマージされると、プルリクエスト2も自動的に「マージ済み」として扱われます。
これは、GitHubが「プルリクエスト1によって、プルリクエスト2が取り込もうとしていた変更内容がすでにマージ先に含まれた」と判断するためです。結果として、プルリクエスト2は実質的にマージされた状態になります。
ここが問題!「クローズ」ではなく「マージ済み」が招く予期せぬ事態
この挙動で特に注意が必要なのは、プルリクエスト2がクローズではなくマージ済みとして扱われる点です。
多くのリポジトリでは、マージ済みのブランチは不要と判断し、自動削除する設定を有効にしていることがあります。
この設定が有効になっていると、以下のような連鎖反応が起きてしまいます。
1.プルリクエスト1をマージする。
2.ブランチ1が自動的に削除される。
3.プルリクエスト2が自動的に「マージ済み」として扱われる。
4.ブランチ2も自動的に削除される。
さらに厄介なのは、ブランチ2からさらに派生したブランチ3があり、ブランチ3からブランチ2に向けたPRが存在していた場合です。
ブランチ2が削除されたことで、ブランチ3からのプルリクエストのマージ先が自動的にデフォルトブランチ(通常はmain)に切り替わってしまうのです。これはドラフト状態のプルリクエストでも同様に発生し、この自動的な挙動を止める設定はありませんでした。
この状態が起きた事を確認するには
このような自動的なブランチ削除やマージ先の変更は、混乱を招く可能性があります。ブランチの自動削除は便利な機能なので無効にするのは難しいですが、意図しない挙動が起きたことを確認できるようしておくことが重要になるかと思います。
今回のケースでは、プルリクエスト2は実際にマージされたわけではないため、メインブランチの履歴にはプルリクエスト2がマージされたという記録は残りません。
そのため、もしこの現象が起きたと思われた場合は、以下の手順で確認できます。
1.「マージ済み」になったプルリクエスト2のステータス変更時刻を確認します。
2.その時刻周辺のメインブランチのコミット履歴を調べます。
3.プルリクエスト2の番号に該当するマージコミットが履歴に見当たらない
今回の事象(同一内容のプルリクエストが別のPRのマージによって「マージ済み」とされた)が、発生した可能性が高いと判断できます。