Git rebaseの使い方!コミット履歴をきれいに整理する方法

git
\ Gitがよく分からない初心者の方へ /
さわっておぼえるGit入門
Gitがよく分からない初心者でも、
この1冊で基本操作を一通り理解できます。
👉 Amazonで詳しく見る
Kindle Unlimitedなら無料で読めます
▶ 無料で読む(Kindle Unlimited)
\ Amazonセール開催中! /

今回は、Gitのrebaseについて解説しています。
Gitを使っていると、次のような場面はありませんか?

  • コミット履歴がごちゃごちゃして見づらい
  • ブランチを統合したら履歴が複雑になった
  • mergerebaseの違いが分からない
  • GitHubのプルリクエスト前に履歴を整理したい

このような場合に便利なのがgit rebaseです。

rebaseを使うと、コミット履歴を一直線に整理できるため、プロジェクト全体の履歴が見やすくなります。
この記事では、Git rebaseの基本的な使い方から、mergeとの違い、安全に利用するための注意点まで解説していきます。

Git rebaseとは

Git rebaseとは、あるブランチの変更履歴を別のブランチの先頭へ付け替える機能です。
例えば、次のような履歴があるとします。

main
A --- B --- C

feature
       \
        D --- E

mainブランチのBコミットの地点からfeatureブランチを作って、D・Eとコミットを重ねた状態です。
mainブランチの方はBコミットの後に、Cコミットを重ねています。

この状態でfeatureブランチに対してrebaseを実行すると、下記のようになります。

main
A --- B --- C

feature
             \
              D' --- E'

mainコミットの最新からfeatureブランチのコミットが足されたような形になります。

一見同じように見えますが、DEは新しいコミットとして作り直されています。
そのため、履歴が一直線になり、あとから変更履歴を追いやすくなります。

Git rebaseとmergeの違い

rebase機能とよく比較されるのがmergeです。

mergeの場合

マージの場合は、下記のようにマージ先のブランチ(main)に変えて
マージ元のブランチ(feature)を取り込みます。

git switch main
git merge feature

そうすると、履歴は次のようになります。

A --- B --- C -------- M
       \            /
        D --- E ----

mainブランチのBコミットから、featureブランチのD・Eコミットをmainブランチにマージしました。
このときにマージコミット(M)が作成されます。

このようにgit mergeでは、マージされた履歴が残りますが、履歴がわかれることになります。

rebaseの場合

リベースの場合になりますが、下記のように操作することで

git switch feature
git rebase main

履歴は次のようになります。

A --- B --- C (main) --- D' --- E' (feature)

このように履歴が一直線になり、わかりやすくなります。

どちらを使うべき?

一般的には次のように使い分けます。

操作 おすすめ
履歴をきれいにしたい rebase
履歴をそのまま残したい merge
プルリク前の整理 rebase
本番ブランチへの統合 merge

Git rebaseの基本的な使い方

例えばmainの最新変更をfeatureへ取り込みたい場合です。
まずはfeatureブランチへ移動します。

git switch feature

続いてrebaseを実行します。

git rebase main

これだけです。
実行後の履歴は次のようになります。

main
A --- B --- C

feature
             \
              D' --- E'

mainブランチの最新コミット、Cに続いて、featureブランチのD'E'が作られます。

rebase中にコンフリクトが発生した場合

rebase中に同じ箇所を編集していると、コンフリクトが発生することがあります。
例えば次のようなエラーが表示されます。

CONFLICT (content): Merge conflict in sample.php

その場合は対象ファイルを修正します。

git status

修正後に追加します。

git add .

そしてrebaseを再開します。

git rebase --continue

もし作業を中止したい場合は、下記コマンドを実行します。

git rebase --abort

これでrebase前の状態へ戻せます。

コミットをまとめる(git rebase -i)

rebaseの便利な機能として、コミットをまとめることもできます。
例えば次のような履歴があるとします。

A 修正
B 修正
C 修正

細かくコミットしすぎてしまった場合、下記のようにrebaseコマンドに
-iオプションをつけて実行します。(HEAD~3で3つ前のコミットです)

git rebase -i HEAD~3

すると、下記のような画面が表示されます。

pick aaa A修正
pick bbb B修正
pick ccc C修正

これを次のように変更します。

pick aaa A修正
squash bbb B修正
squash ccc C修正

そして保存すると、3つのコミットがA修正の1つにまとめられます。
プルリクエスト前の履歴整理でよく利用される方法です。

Git rebase後にpushできない場合

rebaseを実行するとコミットIDが変わります。
そのため、すでにリモートへpush済みの場合は通常のpushが失敗します。

git push
! [rejected]

この場合は強制的に履歴を更新します。

git push --force-with-lease

--forceよりも安全なため、基本的にはこちらを利用しましょう。

Git rebaseの注意点

git rebaseを使う時の注意点です。

共有ブランチには使わない

他のメンバーも利用しているブランチでrebaseすると、コミット履歴が書き換わります。
すると他の開発者の履歴とずれてしまい、トラブルの原因になります。

基本的には次のルールがおすすめです。

  • 自分専用ブランチ → rebase OK
  • 共有ブランチ → rebase非推奨

mainブランチでは慎重に扱う

本番運用中のブランチでrebaseすると履歴が変更されます。
チーム開発では特に注意しましょう。

Git rebaseとmergeはどちらがよい?

結論としては、開発中はrebase、統合時はmergeという使い分けが分かりやすいです。
例えば次の流れです。

  1. featureブランチで開発
  2. rebaseで最新mainを取り込む
  3. Pull Requestを作成
  4. mergeでmainへ統合

この方法なら履歴も見やすく、安全に運用できます。
rebaseは開発ブランチへの取り込みや、コミットをまとめるなど、開発中のブランチで使うと良いかと思います。

まとめ

git rebaseを使うと、コミット履歴をきれいに整理できました。
主なコマンドはこちらです。

git rebase main

コンフリクト解決後の再開

git rebase --continue

中止する場合

git rebase --abort

コミットをまとめる場合

git rebase -i HEAD~3

ただし、rebaseは履歴を書き換える操作です。
共有ブランチでは慎重に利用し、基本的には自分の作業ブランチで使うようにしていきましょう。

コメント