ブログ記事

git rebaseマスターガイド - 履歴を美しく保つテクニック

gitの履歴がぐちゃぐちゃで恥ずかしい...そんな悩みを解決!インタラクティブリベースを使って、プロフェッショナルなコミット履歴を作る方法を実例とともに解説します。

Tips
git version-control rebase best-practices workflow
git rebaseマスターガイド - 履歴を美しく保つテクニックのヒーロー画像

こんにちは!今日は多くの開発者が苦手意識を持っている「Git rebase」について、できるだけ分かりやすく解説していきます。

正直に言うと、私も最初は rebase が怖くて仕方ありませんでした。「履歴を書き換える」なんて聞くと、何か取り返しのつかないことをしてしまいそうで…。でも、一度理解してしまえば、これほど便利なツールはありません!

なぜrebaseが必要なの?

チーム開発をしていると、こんな経験ありませんか?

$ git log --oneline
a1b2c3d fix: typo修正
e4f5g6h WIP: 一旦コミット
i7j8k9l fix: あ、テスト忘れてた
m1n2o3p feat: 新機能追加(やっと完成)

「WIP」とか「一旦コミット」とか…正直、他の人に見られたくないですよね。これをキレイにまとめられるのが rebase の魅力です!

インタラクティブリベースの基本

まずは基本から。過去 3 つのコミットを整理したい場合:

$ git rebase -i HEAD~3

すると、こんな画面が表示されます:

pick a1b2c3d fix: typo修正
pick e4f5g6h WIP: 一旦コミット
pick i7j8k9l fix: あ、テスト忘れてた

# Rebase m1n2o3p..i7j8k9l onto m1n2o3p (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# d, drop = remove commit

よく使うコマンドたち

実際によく使うのは、この 4 つです:

  1. pick(そのまま残す): デフォルト。何も変更しない
  2. squash(まとめる): 前のコミットと合体。メッセージは両方残る
  3. fixup(まとめる): squash と同じだけど、メッセージは捨てられる
  4. reword(メッセージ変更): コミット内容はそのまま、メッセージだけ変更

実践例1: WIPコミットをまとめる

開発中によくあるパターンですね。作業途中で何度もコミットして、最後にまとめたい場合:

# 現在の履歴
$ git log --oneline -5
5d4f3e2 feat: ユーザー認証機能を追加
1a2b3c4 fix: エラーメッセージの修正
9f8e7d6 WIP: 認証ロジック実装中
3c2b1a0 WIP: ログイン画面作成
7e6d5c4 feat: 認証APIの基本構造を追加

これをインタラクティブリベースで整理:

$ git rebase -i HEAD~5

エディタで以下のように変更:

pick 7e6d5c4 feat: 認証APIの基本構造を追加
squash 3c2b1a0 WIP: ログイン画面作成
squash 9f8e7d6 WIP: 認証ロジック実装中
pick 1a2b3c4 fix: エラーメッセージの修正
pick 5d4f3e2 feat: ユーザー認証機能を追加

保存して閉じると、新しいコミットメッセージを編集する画面が出てきます。ここで、きちんとしたメッセージに書き直しましょう:

feat: 認証機能の基本実装

- 認証APIの基本構造を追加
- ログイン画面のUIを実装
- 認証ロジックとバリデーションを追加

実践例2: コミットメッセージの修正

「あ、タイポしちゃった…」という時の対処法:

# 最新のコミットメッセージを修正
$ git commit --amend -m "新しいメッセージ"

# 過去のコミットを修正したい場合
$ git rebase -i HEAD~3
# 修正したいコミットを「pick」から「reword」に変更

実践例3: 不要なコミットの削除

デバッグ用の console.log を追加したコミットとか、要らないですよね:

$ git rebase -i HEAD~4
pick a1b2c3d feat: 新機能追加
drop e4f5g6h debug: console.log追加  # これを削除
pick i7j8k9l fix: バグ修正
pick m1n2o3p docs: README更新

コンフリクトが起きたときは

rebase で一番怖いのがコンフリクト。でも、落ち着いて対処すれば大丈夫です:

# コンフリクトが発生!
$ git rebase -i HEAD~3
error: could not apply a1b2c3d...

# 1. まず状態を確認
$ git status

# 2. コンフリクトを解決(通常のマージと同じ)
$ vim conflicted_file.js  # コンフリクトを修正

# 3. 修正したファイルをステージング
$ git add conflicted_file.js

# 4. rebaseを続行
$ git rebase --continue

# もし諦めたい場合は
$ git rebase --abort

プロのワークフロー

私が実際に使っているワークフローを紹介します:

1. 作業ブランチでは気にせずコミット

$ git add .
$ git commit -m "WIP: とりあえず動いた"
$ git commit -m "fix: あ、これ忘れてた"
$ git commit -m "もう一個修正"

2. PRを出す前に履歴を整理

# 履歴を確認
$ git log --oneline -10

# インタラクティブリベースで整理
$ git rebase -i origin/main

# きれいな履歴に!
$ git log --oneline -3
a1b2c3d feat: ユーザープロフィール機能を実装
e4f5g6h test: プロフィール機能のテストを追加
i7j8k9l docs: API仕様書を更新

3. フォースプッシュ(注意!)

# 自分の作業ブランチなら問題なし
$ git push --force-with-lease origin feature/user-profile

--force-with-lease を使うのがポイント。これなら他の人の変更を誤って消すリスクが減ります。

rebaseのゴールデンルール

  1. 公開されたブランチではrebaseしない: main や develop では絶対 NG
  2. 他の人と共有しているブランチでは慎重に: 事前に相談しよう
  3. フォースプッシュは自分のブランチだけ: そして --force-with-lease を使う
  4. 困ったら git reflog: 履歴は実は残っているので、復元可能

よくある質問

Q: rebaseとmergeの使い分けは?

私の基準はシンプルです:

  • 自分の作業ブランチ: rebase(履歴をきれいに)
  • 共有ブランチへの統合: merge(履歴を残す)

Q: rebaseで失敗したらどうしよう?

大丈夫、Git は優秀です:

# rebase前の状態を確認
$ git reflog

# 戻したいコミットを見つけて
$ git reset --hard HEAD@{2}

まとめ

Git rebase は最初は怖いかもしれませんが、慣れれば本当に便利なツールです。特にチーム開発では、きれいなコミット履歴は後から見返すときにとても助かります。

私も最初は「とりあえず commit」の連続でしたが、rebase を覚えてからは自信を持って PR を出せるようになりました。みなさんも、まずは自分の作業ブランチで練習してみてください!

次回は「正規表現パズル」について解説します。メールアドレスの検証って、実は奥が深いんですよ…!

この記事は役に立ちましたか?

Daily Hackでは、開発者の皆様に役立つ情報を毎日発信しています。