前書き
GitHubで Pull Request をマージする際には、3種類の方法がある。
これまでの開発現場では、開発内容を develop や staging ブランチに統合する際は Squash and merge、本番ブランチ(master や main)に統合する際は Create a merge commit を使用していた。
しかし、そもそもGitHubには3種類のマージ方法があり、それぞれの違いを正確に理解しないまま運用していたのが現状である。 今回は、改めてそれぞれのマージ方法の仕組みと特徴を理解するため、備忘録として以下の3種類について整理する。
- Create a merge commit(マージコミット)
- Squash and merge(スカッシュマージ)
- Rebase and merge(リベースマージ)
マージの概要
- 開発ブランチ(
featureブランチなど)での変更をメインブランチ(mainやdevelop)に統合する操作 - GitHub上では
Pull Requestを通してこの統合作業を行う
事前準備
- 今回のマージ方法の違いを理解するために、まずはテスト用のブランチを準備する
- 本記事では、
mainブランチをベースとして、作業用のtestブランチを作成して検証する
Create a merge commit(マージコミット)
- testブランチのすべてのコミットをそのまま
mainブランチに統合する方法 - マージの際に、新しく「マージコミット」という特別なコミットを1つ作成し、2つのブランチをつなぎ合わせる
- 履歴が明確に残るため、どのような変更が行われたかを正確に追跡できる
- 懸念点として、細かいコミットが多い場合、履歴が複雑になりやすい
コマンド
git checkout main
git merge test
git push origin main
Gitの動き(図)
マージコミット前
main: A---B
\
test: C---D
マージコミット後
- マージ後、Gitの履歴には「Merge branch
test」というマージコミットが追加される - マージコミットのメッセージには、元のプルリクエスト(PR)へのリンクが自動で付与されるため、後から履歴をたどってPRの内容(どんなコミットが含まれていたか)を確認できる
- 過去に作られたコミットは、他のブランチやマージコミットから参照されている限り、Gitの履歴上に残り続ける
# Eは、マージコミット
# mainとtestの両方を統合した証拠として残る
main: A---B---------E
\ /
C---D
Squash and merge(スカッシュマージ)
-
testブランチ内の複数のコミットを1つにまとめてからmainに統合する方法 - 「スカッシュ(squash)」とは「押しつぶす」という意味で、細かいコミットを1つに集約することを指す
- 履歴が簡潔になり、
mainブランチのログを見やすく保てる - 懸念点として、個々のコミット履歴は失われるため、細かい開発過程を追跡できなくなる
コマンド
git checkout main
git merge --squash test
git commit -m "Add new feature from test"
git push origin main
Gitの動き(図)
マージコミット前
main: A---B
\
test: C---D---E
マージコミット後
-
testブランチ内の複数コミットを1つにまとめてmainブランチへ取り込み、履歴をシンプルに保ちながら変更内容を要約して残す
# testブランチの3つのコミット(C, D, E)は1つのコミットFとしてまとめられる
# mainの履歴はシンプルに保たれる
main: A---B---F
Rebase and merge(リベースマージ)
-
testブランチの基点(ベース)をmainの最新コミットに付け替える方法 - 「リベース(rebase)」とは、履歴を書き換えて直線的に並べる操作を指す
- 履歴が一直線になり、どの変更がいつ行われたかを明確に把握できる
- 懸念点として、履歴を書き換えるため、共有ブランチで使うとコンフリクト(競合)が起きやすくなる
コマンド
git checkout test
git rebase main
git checkout main
git merge test
git push origin main
Gitの動き(図)
マージコミット前
main: A---B
\
test: C---D---E
マージコミット後
-
testブランチの変更内容をmainブランチの最新コミットの直後に付け替え、全ての変更を保ったまま履歴を1本の直線に整理する
# C', D', E' は、mainの末尾に付け替えられた新しいコミット
# 履歴が1本の直線として整理される
main: A---B---C'---D'---E'
参考資料
- [Git 公式] Git
- [GitHub 公式]GitHub上のマージ方法について
- [公式] about-merge-methods-on-github.md
- What's the Difference Between the 3 Github Merge Methods?
感想
今回は、GitHubで使用されているマージ方法について理解を深めました。これまでは一般的な通説をもとにマージの仕方を選んでいましたが、今回あらためてそれぞれの仕組みを調べ、違いを正確に理解できてとても良かったです。
マージの方法は想像以上に奥が深く、運用方針や開発規模によって最適な手法が変わることを実感しました。今後は今回の学びを活かし、チーム開発でもより適切なマージ運用を行っていきたいと思います。