よくある話が、ブランチを統合するときに、mergeとrebaseのどちらを使うか迷う場面。
ところが、この2つはやりたいこと自体は同じでも、コミット履歴の残り方がまったく違う。
そこで、この記事では「履歴をどう残したいか」を軸にした使い分けを整理した。

mergeとrebase、何が違うのか
| 項目 | merge | rebase |
|---|---|---|
| 履歴の見た目 | 分岐・統合がそのまま残る | 一直線に並び替えられる |
| コミット本体 | 変更されない | 再作成される(ハッシュが変わる) |
| マージコミット | 作られる | 作られない(fast-forwardになる) |
| 共有ブランチでの安全性 | 安全 | 他の人がpull済みだと事故りやすい |
mergeは事実をそのまま記録し、rebaseは記録を書き直してきれいに見せる。この違いが、そのまま使い分けの判断軸になる。
mergeの基本
featureブランチの内容を、mainブランチに統合する基本の書き方。
git checkout main
git merge feature分岐点からの変更をまとめる「マージコミット」が自動的に作られ、両方のブランチの履歴がそのまま残る。
rebaseの基本
featureブランチの分岐元を、mainブランチの最新コミットに付け替える。
git checkout feature
git rebase mainfeatureブランチのコミットが1つずつ再作成され、まるで最初からmainの最新の上で作業していたかのような、一直線の履歴になる。
コミットが再作成される以上、コミットハッシュはすべて変わる。ここがmergeとの決定的な違い。
使い分けの判断軸
判断軸はシンプルで、「そのブランチを他の人がすでに手元にpullしているかどうか」。
- 共有済みのブランチ(main等)に統合する → merge(履歴を書き換えないので安全)
- 自分専用のfeatureブランチを整理したい → rebase(誰にも影響しない)
他の人が同じブランチをpull済みの状態でrebaseすると、コミットハッシュの食い違いが起きて、次のpullで大量のコンフリクトを引き起こすことがある。すでに公開したコミットはrebaseしない、というのがGitの基本ルール。
interactive rebaseでコミットを整理する
rebaseにはもう一つ、統合とは別の使い道がある。push前の自分のブランチのコミットを整理する用途。
git rebase -i HEAD~3エディタが開き、直近3件のコミットを一覧できる。pickをsquashに書き換えると、そのコミットを1つ前にまとめられる。「動作確認用の細かいコミット」を、pushする前に意味のある単位にまとめ直すときに使う。
この使い方は自分のブランチ内で完結するので、他の人に影響を与える心配はない。
まとめ
共有ブランチへの統合はmerge、自分だけのブランチの整理はrebase。「もう他の人が見ているかどうか」で選べば、事故らずに使い分けられる。
rebase中にコンフリクトが起きたらどうすればいいですか?
該当ファイルを開いて手動で解消し、git addでステージしたあとgit rebase --continueで再開します。rebase自体をやめたい場合はgit rebase --abortで開始前の状態に戻せます。
GitHubのPull RequestでよくあるSquash and mergeはmerge・rebaseのどちらですか?
どちらとも異なる第3の統合方法です。featureブランチの全コミットを1つのコミットにまとめてmainへ追加します。featureブランチ内の細かいコミットを気にせず、PR単位で1コミットとして履歴を残したい場合によく使われます。
誤ってpush済みのコミットをrebaseしてしまいました。どうすればいいですか?
他の人がまだpullしていなければ、git push --force-with-leaseで上書きできます。すでに誰かがpull済みの場合は、チームに連絡してrebase前の状態に揃えてもらう必要があります。

コメント