コミットをマージする
pull request で既定の [pull request のマージ] オプションをクリックすると、機能ブランチからのすべてのコミットがマージ コミット内のベース ブランチに追加されます。 pull request は、--no-ff
オプションを使用してマージされます。
pull request をマージするには、リポジトリの書き込みアクセス許可が必要です。
コミットをスカッシュしてマージする
pull request で [スカッシュとマージ] オプションを選ぶと、その pull request のコミットが 1 つのコミットにスカッシュされます。 トピックブランチからコントリビュータの個々のコミットをすべて見る代わりに、コミットは1つのコミットにまとめられ、デフォルトブランチにマージされます。 スカッシュされたコミットを含む pull request は、早送りオプションを使用してマージされます。
pull request をスカッシュしてマージするには、リポジトリに書き込みアクセス許可が必要であり、リポジトリでスカッシュ マージが許可されている必要があります。
squashとマージは、よりスムーズなGitの履歴をリポジトリに作り出すために利用できます。 作業途中でのコミットは、フィーチャブランチで作業しているときには役立ちますが、必ずしもGitの履歴に残すほど重要とはかぎりません。 デフォルトブランチへのマージに際してそれらのコミットを1つのコミットにsquashすれば、明快なGitの履歴と共にオリジナルの変更を残しておけます。
squash マージのマージメッセージ
スカッシュしてしてマージすると、GitHub によって既定のコミット メッセージが生成されます。これを編集することができます。 リポジトリの構成方法と pull request 内のコミット数 (マージ コミットを除く) にもよりますが、このメッセージには pull request のタイトル、pull request の説明、コミットに関する情報などが含まれます。
コミット数 | まとめ | 説明 |
---|---|---|
単一のコミット | 単一のコミットのコミットメッセージのタイトルと、その後に続くプルリクエスト番号 | 単一のコミットのコミットメッセージの本文テキスト |
複数のコミット | プルリクエストのタイトルと、その後に続くプルリクエスト番号 | squash されたすべてのコミットのコミットメッセージの日付順のリスト |
リポジトリに対してメンテナーまたは管理者のアクセス権を持つユーザーは、スカッシュされたすべてのコミットについて、pull request のタイトル、pull request のタイトルとコミットの詳細、または pull request のタイトルと説明を使うようにリポジトリの既定のマージ メッセージを構成できます。 詳細については、「プルリクエストにコミットの squash を設定する」を参照してください。
長時間にわたるブランチを squash してマージする
pull request のマージ後、pull request のヘッド ブランチでの作業を続ける場合、pull request はスカッシュしてマージしないことをお勧めします。
pull request を作成すると、GitHub によって、ヘッド ブランチとベース ブランチの両方での最近のコミットが特定されます。共通の先祖のコミットです。 プルリクエストを squash してマージすると、GitHub は、共通の先祖のコミット以降に head ブランチで行ったすべての変更を含むコミットをベースブランチに作成します。
このコミットはベースブランチのみで行われ、head ブランチでは行われないため、2 つのブランチの共通の先祖は変更されません。 head ブランチでの作業を続行し、2 つのブランチ間に新しいプルリクエストを作成すると、プルリクエストには、共通の先祖以降のすべてのコミットが含まれます。これには、前のプルリクエストで squash してマージしたコミットも含まれます。 コンフリクトがない場合は、これらのコミットを安全にマージできます。 ただし、このワークフローでは高確率でマージコンフリクトが発生します。 長時間にわたる head ブランチのプルリクエストを squash してマージし続ける場合は、同じコンフリクトを繰り返し解決する必要があります。
コミットをリベースしてマージする
pull request で [リベースとマージ] オプションを選択すると、トピック ブランチ (または head ブランチ) からのすべてのコミットが、マージ コミットなしに個別にベース ブランチに追加されます。 このように、リベースとマージの動作は、線形プロジェクト履歴を維持することで、早送りマージ に似ています。 しかし、リベースは、ベース ブランチのコミット履歴を新しいコミットで書き直すことでこれを実現します。
GitHub でのリベースとマージの動作は、git rebase
とは少し異なっています。 GitHub でリベースしてマージすると、常にコミッター情報が更新され、新しいコミット SHA が作成されますが、GitHub 外の git rebase
は、先祖コミットの上でリベースが発生した場合、コミッター情報は変更されません。 git rebase
の詳細については、Git ドキュメントの「git-rebase」を参照してください。
pull request をリベースしてマージするには、リポジトリに書き込みアクセス許可が必要であり、リポジトリでリベース マージが許可されている必要があります。
git rebase
の視覚的表現については、ProGit ブックの「GitBranching-Rebasing」の章を参照してください。
次の場合、自動的にリベースとマージを行うことはできません。
- プルリクエストにマージコンフリクトがある。
- ベースブランチからヘッドブランチへのコミットのリベースでコンフリクトが生じる。
- たとえば、マージコンフリクトなしにリベースできるものの、マージとは異なる結果が生成されるような場合、コミットのリベースは「安全ではない」と考えられます。
それでもコミットをリベースしたいにもかかわらず、自動的にリベースとマージが行えない場合、次の操作を行う必要があります。
- トピックブランチ (あるいは head ブランチ) をベースブランチにローカルでコマンドラインからリベースする
- コマンド ラインでマージの競合を解決します。
- リベースされたコミットをプルリクエストのトピックブランチ (あるいはリモートの head ブランチ) にフォースプッシュする。
リポジトリでの書き込みアクセス許可を持つすべてのユーザーは、[リベースとマージ] ボタンを使って変更をマージできます。
間接マージ
ヘッド ブランチが外部のベース ブランチに直接的または間接的にマージされている場合は、pull request を自動的にマージできます。 つまり、ヘッド ブランチのチップ コミットがターゲット ブランチのチップから到達可能になった場合です。 たとえば、次のように入力します。
- ブランチ
main
はコミット C にあります。 - ブランチ
feature
はmain
から分岐されており、現在コミット D にあります。このブランチには、main
をターゲットとする pull request があります。 - ブランチ
feature_2
はfeature
から分岐されており、現在コミット E にあります。このブランチにも、main
をターゲットとする pull request があります。
pull request E --> main
が最初にマージされた場合、feature
からのすべてのコミットが main
から到達できるようになったため、pull request D --> main
は "自動的" にマージ済みとしてマークされます。__ コマンド ラインからの main
への feature_2
のマージとサーバーへの main
のプッシュにより、"両方の" pull request がマージ済みとしてマークされます。__
間接マージが発生するのは、pull request のヘッド ブランチ内のコミットがリポジトリの既定のブランチに直接プッシュされる場合か、pull request のヘッド ブランチ内のコミットが別の pull request に存在し、 [マージ コミットの作成] オプションを使ってリポジトリの既定のブランチにマージされる場合のみです。
別の pull request のヘッド ブランチ内に存在するコミットを含む pull request が、 [スカッシュしてマージ] または [リベースしてマージ] オプションを使ってマージされた場合、ベース ブランチに新しいコミットが作成され、別の pull request は自動的にマージされません。
間接的にマージされた pull request は、ブランチ保護ルールを満たしていない場合でも、merged
としてマークされます。