Gitでブランチを統合する際、git merge
とgit rebase
の2つの方法があります。どちらも同じ目的(ブランチの統合)に見えますが...その過程と結果が大きく異なります!
よく仕事でmainブランチ(developブランチ)の内容を取り込むことがあると思いますが、その際にどちらを使うべきか迷うことがあると思います。チームの方針や現在のプロジェクトの状況によって適切な方法を選択することが重要です!
本記事では、git merge
とgit rebase
の違いを実際のコマンド例と図を用いて解説します!
想定シチュエーション
以下のような状況を想定してみましょう:
-
feature/user-authentication
ブランチでユーザー認証機能を開発中 - 同時に他の開発者が
main
ブランチに新しいコミットを追加している - 作業を
main
ブランチに統合する必要がある
初期状態
まず、現在の状況を図で表してみます:
-
A
,B
,C
,D
: mainブランチのコミット -
E
,F
,G
: featureブランチのコミット
git merge の場合
実行コマンド
git switch feature/user-authentication
git merge main
結果の図
現状
merge操作後
-
マージコミットの作成: 新しいコミット
M
(マージコミット)が作成される - 履歴の保持: 両方のブランチの履歴が完全に保持される
- 分岐の維持: 元の分岐構造が残る
メリット
- 履歴が完全に保持される
- 元の作業の流れが分かりやすい
- マージのタイミングが明確
デメリット
- 履歴が複雑になる可能性がある
- マージコミットが多すぎると見づらくなる
git rebase の場合
実行コマンド
git switch feature/user-authentication
git rebase main
結果の図
現状
rebase操作後
-
コミットの再適用: あなたのコミット(
E
,F
,G
)がD
の後に再適用される - 線形な履歴: 直線的な履歴が作成される
-
コミットハッシュの変更: 再適用されたコミットは新しいハッシュ(
E'
,F'
,G'
)になる
メリット
- 履歴が線形で見やすい
- マージコミットが不要
- より整理された履歴
デメリット
- コミットハッシュが変更される
- 既にプッシュ済みのブランチでは危険
- 元の作業のタイミングが分かりにくくなる
実際の開発での使い分け
git merge を使うべき場合
-
プルリクエストのマージ時
作成したプルリクエストをマージしてfeatureブランチで作業することができる# 一旦featureブランチの変更を退避する git stash # 作業中のブランチを最新のmainに合わせる ## リモートブランチから同期が必要な場合 git fetch origin # featureブランチを最新のリモートのmainブランチに合わせる git merge origin/main # 退避した変更を復元する git stash pop
(参考)git stashとは?
https://qiita.com/JavaLangRuntimeException/items/d70dcfa530deaf519af1
-
履歴を完全に保持したい場合
- 重要なマイルストーンの記録
- チームの作業の流れを追跡したい場合
-
共有ブランチの統合時
- 他の開発者と共有しているブランチ
git rebase を使うべき場合
-
ローカルブランチの整理
マージコミットが作成されないので仮にfeatureブランチで作業中にコミットがない場合は以下のように最新のmainブランチに合わせることができる。# 一旦featureブランチの変更を退避する git stash # 作業中のブランチを最新のmainに合わせる ## リモートブランチから同期が必要な場合 git fetch origin # featureブランチを最新のリモートのmainブランチに合わせる git rebase origin/main # 退避した変更を復元する git stash pop
-
コミット履歴を整理したい場合
# 複数の小さなコミットをまとめる git rebase -i HEAD~3
-
線形な履歴を維持したい場合
- プロジェクトで線形履歴の方針を採用している場合
注意点とベストプラクティス
重要な注意点
-
共有ブランチでのリベースは避ける
# 危険!既にプッシュ済みのブランチでリベース git rebase origin/main # 他の開発者に影響
-
マージコンフリクトの解決
- どちらの方法でもコンフリクトは発生する可能性があります
- コンフリクト解決後、適切にコミットまたはリベースを続行
推奨されるワークフロー
- 個人の作業ブランチ: リベースを使用
- プルリクエストのマージ: マージを使用
- リリースブランチ: マージを使用
- git merge: 履歴を完全に保持し、分岐構造を維持
- git rebase: 線形な履歴を作成し、整理された履歴を実現
どちらを選ぶかは、プロジェクトのポリシーやチームの方針によって決まります。重要なのは、一貫性を保つことだと思います!
参考コマンド
# 履歴の可視化
git log --oneline --graph --all
# ブランチの状況確認
git branch -vv
# リモートブランチの取得
git fetch origin
# マージとリベースの実行
git merge origin/main
git rebase origin/main
このように、git merge
とgit rebase
は同じ目的を達成する異なるアプローチです。状況に応じて適切な方法を選択することで、より効率的なGitワークフローを実現できます!適切な方法を選択することが重要です!