Skip to main content

GitHub上のマージ方法について

リポジトリへのプッシュ アクセスを持つ共同作成者に対し、pull request をさまざまなマージ オプションを使ってマージしたり、リポジトリのすべての pull request に特定のマージ方法を強制したりすることを許可できます。

ワークフローのニーズや Git 履歴管理の設定に合わせて、pull request のマージ オプションを設定できます。 詳しくは、「プルリクエストマージを設定する」を参照してください。コミットsquashingあるいはリベースのようなマージの1つの種類を、リポジトリでその方法だけを有効化することで強制できます。

pull request で既定の [pull request のマージ] オプションをクリックすると、機能ブランチからのすべてのコミットがマージ コミット内のベース ブランチに追加されます。 pull request は、--no-ff オプションを使用してマージされます。

pull request をマージするには、リポジトリの書き込みアクセス許可が必要です。

標準的なマージとコミットのフローの図。機能ブランチからのコミットと追加のマージ コミットの両方が "main" に追加されています。

デフォルトのマージ方法では、マージコミットが作成されます。 直線状のコミット履歴を強制して、保護されたブランチにマージコミットをプッシュできないようにすることができます。 詳しくは、「保護されたブランチについて」をご覧ください。

マージコミットのsquash

pull request で [スカッシュとマージ] オプションを選ぶと、その pull request のコミットが 1 つのコミットにスカッシュされます。 トピックブランチからコントリビュータの個々のコミットをすべて見る代わりに、コミットは1つのコミットにまとめられ、デフォルトブランチにマージされます。 スカッシュされたコミットを含む pull request は、早送りオプションを使用してマージされます。

pull request をスカッシュしてマージするには、リポジトリに書き込みアクセス許可が必要であり、リポジトリでスカッシュ マージが許可されている必要があります。

コミットのスカッシュの図。機能ブランチからの複数のコミットが、main に追加されるただ 1 つのコミットに結合されています。

squashとマージは、よりスムーズなGitの履歴をリポジトリに作り出すために利用できます。 作業途中でのコミットは、フィーチャブランチで作業しているときには役立ちますが、必ずしもGitの履歴に残すほど重要とはかぎりません。 デフォルトブランチへのマージに際してそれらのコミットを1つのコミットにsquashすれば、明快なGitの履歴と共にオリジナルの変更を残しておけます。

コミットの squash を有効化する前に、以下の欠点について考慮してください:

  • 特定の変更が元々いつ行われたのか、そして squash されたコミットを誰が作成したのかという情報が失われます。
  • squash してマージした後もプルリクエストの head ブランチで作業を続け、同じブランチ間に新しいプルリクエストを作成すると、以前 squash してマージしたコミットが新しいプルリクエストにリストされます。 また、連続するプルリクエストごとに繰り返し解決しなければならないコンフリクトが発生する場合もあります。 詳しくは、「プルリクエストのマージについて」をご覧ください。
  • "SHA" あるいは "hash" ID を使う Git コマンドの中には、オリジナルのコミット中の SHA ID が失われるので使うことが難しくなるものが生じるかもしれません。 たとえば、git rerere を使用しても効果がないことがあります。

詳しくは、「プルリクエストにコミットの squash を設定する」をご覧ください。

リベースとコミットのマージ

pull request で [リベースとマージ] オプションを選択すると、トピック ブランチ (または head ブランチ) からのすべてのコミットが、マージ コミットなしに個別にベース ブランチに追加されます。 このように、リベースとマージの動作は、線形プロジェクト履歴を維持することで、早送りマージ に似ています。 しかし、リベースは、ベース ブランチのコミット履歴を新しいコミットで書き直すことでこれを実現します。

GitHub Enterprise Server でのリベースとマージの動作は、git rebase とは少し異なっています。 GitHub でリベースしてマージすると、常にコミッター情報が更新され、新しいコミット SHA が作成されますが、GitHub 外の git rebase は、先祖コミットの上でリベースが発生した場合、コミッター情報は変更されません。 git rebase の詳細については、Git ドキュメントの「git-rebase」を参照してください。

pull request をリベースしてマージするには、リポジトリに書き込みアクセス許可が必要であり、リポジトリでリベース マージが許可されている必要があります。

git rebase の視覚的表現については、ProGit ブックの「GitBranching-Rebasing」の章を参照してください。

コミットのリベースを有効化する前に、以下の欠点について考慮してください:

  • リポジトリの共同作成者は、GitHub で [リベースとマージ] オプションを使う前に、コマンド ラインでリベースし、競合があれば解決して、変更を pull request のトピック ブランチ (またはリモートの head ブランチ) にフォース プッシュすることが必要な場合があります。 フォースプッシュは、コントリビューターが他者が作業のベースとしている作業を上書きすることがないよう、慎重に行わなければなりません。 [Rebase and merge] オプションが GitHub で無効になるタイミングや、それをもう一度有効にするためのワークフローの詳細については、「プルリクエストのマージについて」を参照してください。

  • pull request で Rebase と Merge オプションを使用する場合は、ヘッド ブランチのコミットがコミット署名の検証なしでベース ブランチに追加されることに注意することが重要です。 このオプションを使用すると、元のコミットのデータとコンテンツを使用して、GitHub によって変更されたコミットが作成されます。 つまり、GitHub は、このコミットを本当に作成していないため、汎用システム ユーザーとして署名することはできません。 GitHub では、コミッターの秘密署名キーにアクセスできないため、ユーザーの代わりにコミットに署名できません。

    これを回避するには、ローカルでリベースとマージを行い、変更を pull request のベース ブランチにプッシュします。

詳しくは、「プルリクエストにコミットのリベースを設定する」をご覧ください。