結論
先に結論からお伝えすると、以下が本記事でお伝えしたいことです。
本記事でお伝えしたいこと
ブランチAがブランチBの全てのコミット履歴を含む場合、PR Aをマージすると、PR Bも自動で一緒にマージされ(たとGitによって判断され)てしまう
※ブランチA, BとPR A, Bはそれぞれ以下の通り
ブランチA:developブランチから切ったfeatureブランチA
ブランチB:developブランチから切ったfeatureブランチB
PR A:「ブランチAをdevelopブランチにマージする」プルリクエスト
PR B:「ブランチBをdevelopブランチにマージする」プルリクエスト
「結論」の具体例
上記の具体例として、以下の1.~4.のようなシナリオがあります。
1. featureブランチAの作成と開発
- developブランチから切った、「featureA」というfeatureブランチを作成
- featureA上で、新しい機能Aを追加し、以下のコミットを実行
git commit -m "新機能Aを追加"
- featureAをdevelopブランチへマージするプルリクエストを発行
2. featureブランチBの作成と開発
- developブランチから切った、「featureB」というfeatureブランチを作成
- featureB上で、新しい機能Bを追加し、以下のコミットを実行
git commit -m "新機能Bを追加"
- featureBをdevelopブランチへマージするプルリクエストを発行
3. featureBをfeatureAにマージして取り込み
- 何かしらの理由で、featureBをfeatureAにマージする必要が生じたため、ブランチをfeatureAに切り替えた上で、以下のように、featureBをfeatureAにマージ
git merge featureB
ポイント
このマージにより、featureAはfeatureBのコミット履歴を全て含んだ状態となります。
4. プルリクエストAをマージ
- プルリクエストAのマージを実行
上記1.~4.のシナリオを実行すると、結果として、プルリクエストAだけでなく、プルリクエストAと一緒にプルリクエストBも、自動的にマージが完了した状態となります。
上記の事象が起こる理由
- 一言で言うと、Gitの仕様です。
- 上記の例で言うと、3.が終了した時点で、ブランチAは、ブランチBを取り込んだ状態(「新機能Bを追加」といったブランチBの全てのコミットを全て含んだ状態)となっています。
- そして、4.でプルリクエストAのマージを行うことにより、(ブランチBを取り込んだ)ブランチAがdevelopブランチに取り込まれるので、あたかもブランチBも取り込まれてマージされたような状態となります。
- 言い換えれば、あたかもプルリクエストBもマージされた状態となり、プルリクエストBが不要となります。
※というかそもそも、「新機能Bを追加」といったブランチBの全ての変更内容はすでにdevelopブランチへ反映されてしまっており、ブランチBをdevelopブランチにマージしようにも、ブランチBとdevelopブランチの差分が無くなってしまったのでマージができない - そして、以上を踏まえた上でGitが、「プルリクエストBはすでに取り込まれて処理済みの状態となった」と判断し、プルリクエストBが自動的にclosedの状態(処理済みの状態)となってしまうのです。
補足:マージの順番
- 上記の例では、プルリクエストAを先にマージすると、もう片方のプルリクエストBが自動的にclosedとなりましたが、プルリクエストAではなく、プルリクエストBを先にマージした場合、もう片方のプルリクエストAは自動的にclosedの状態となりません。
- 理由は、プルリクエストBをマージしても、ブランチBにはブランチAのコミット履歴は含まれておらず、ブランチAとdevelopブランチには差分が存在し、ブランチAをdevelopブランチへマージするというプルリクエストAが成立するためです。
まとめ
上記のようなGitの挙動を知っておくことで、意図しないマージによる混乱を防げるかと思います。正しい運用でトラブルを防ぎましょう。
最後までお読み頂き、ありがとうございました!この記事が少しでも参考になれば幸いで