Git rebaseを使いこなし、クリーンで分かりやすいコミット履歴を構築しましょう。
このガイドでは、Git rebaseの基本的な概念から、実際の開発現場で役立つ実践的なテクニックまで、具体例を交えて詳しく解説します。複雑な履歴を整理し、チーム開発の効率を向上させるための秘訣を学びましょう。
Contents
Git Rebaseとは?基本概念とMergeとの違い

Git rebaseは、コミット履歴を「再構築」するための強力なコマンドです。既存のコミットを別のベースの上に適用し直すことで、より直線的で分かりやすい履歴を作成できます。これは、特に共有される前のローカルブランチの整理に非常に有効です。
多くの開発者がrebaseとmergeのどちらを使うべきか迷いますが、それぞれの目的と影響を理解することが重要です。rebaseは履歴を書き換えるため、共有済みのブランチには慎重な使用が求められます。
Rebaseの仕組み:コミットの付け替え
Rebaseの最も基本的な動作は、あるブランチのコミットを別のブランチの最新コミットの上に「移動」させることです。具体的には、対象ブランチの変更を一時的に取り消し、ターゲットブランチの最新状態をベースとしてから、元の変更を一つずつ再適用します。これにより、マージコミットを発生させることなく、ブランチの変更を統合できます。
たとえば、featureブランチで作業中にmainブランチに新しいコミットが追加された場合、featureブランチをmainブランチにrebaseすると、featureブランチのコミットがmainの最新コミットの直後に位置するように変更されます。
Mergeとの決定的な違い
Git mergeは、2つのブランチの履歴を統合する際に、新しい「マージコミット」を作成します。このマージコミットは、両方のブランチの変更を結合したことを示し、両方の履歴が並行して存在していたことを明確に記録します。これにより、履歴は枝分かれした状態を保ち、後から変更の経緯を追跡しやすくなります。
一方、Git rebaseはマージコミットを作成せず、ブランチのコミットを線形な履歴に再配置します。これにより、履歴は一直線になり、あたかもすべての変更が最初から一つのブランチで行われたかのように見えます。この違いこそが、rebaseが「履歴を書き換える」と表現される理由です。
Mergeは「何を統合したか」を重視し、rebaseは「どのように変更が積み重なったか」を重視すると考えると理解しやすいでしょう。
Git Rebaseの主要なユースケース

Git rebaseはその強力な機能ゆえに、様々なシナリオで活用できます。特に、自身のローカルブランチを整理し、他の開発者との共同作業をスムーズに進めるために不可欠なツールです。ここでは、rebaseが特に輝く主要なユースケースを詳しく見ていきましょう。
ブランチを最新の状態に保つ
開発中にmainブランチ(または他のベースブランチ)に新しいコミットが追加されることはよくあります。自分の作業ブランチをmainの最新状態に追従させることで、後々のマージコンフリクトを減らし、最新のコードベースで開発を進めることができます。
この操作は、featureブランチにいる状態で以下のコマンドを実行します。
git checkout feature
git rebase mainこれにより、featureブランチのコミットはmainの最新コミットの上に再適用され、履歴が直線的になります。このプロセス中にコンフリクトが発生する可能性がありますが、その解決方法は後述します。
複数の小さなコミットをまとめる(Squash)
開発中は、機能の実装中に多くの小さなコミットを作成しがちです。例えば、「 typo修正」「テストコード追加」「デバッグ用ログ削除」といったコミットが多数発生することがあります。これらをそのままプッシュすると、履歴が煩雑になり、後から変更内容を追うのが困難になります。
インタラクティブrebaseを使用すると、これらの小さなコミットを論理的な一つのコミットにまとめることができます。これにより、各コミットが明確な目的を持つようになり、コードレビューもしやすくなります。
git rebase -i HEAD~3このコマンドは、直近3つのコミットを対象にインタラクティブrebaseを開始します。エディタが開き、各コミットに対して「pick」「squash」「fixup」などの操作を選択できます。具体的な方法は次のセクションで詳しく説明します。
コミットメッセージの修正
コミットメッセージは、後から変更履歴を理解するために非常に重要です。しかし、誤字脱字や説明不足のメッセージでコミットしてしまい、後から修正したいという状況はよく発生します。
直前のコミットメッセージを修正する場合は、git commit --amendコマンドが便利です。
git commit --amend -m "新しいコミットメッセージ"これより前のコミットメッセージを修正したい場合は、インタラクティブrebaseを使用して「reword」オプションを使います。
インタラクティブRebaseの活用

インタラクティブrebase (git rebase -i) は、Git rebaseの最も強力な機能の一つです。これを使うことで、複数のコミットに対して様々な操作を適用し、コミット履歴を思い通りに編集できます。まるでタイムマシンで過去に戻り、履歴を整理するような感覚です。
このセクションでは、インタラクティブrebaseで利用できる主要なコマンドと、その具体的な使い方を解説します。
インタラクティブRebaseの開始
インタラクティブrebaseを開始するには、git rebase -i <コミットハッシュまたは参照>コマンドを使用します。例えば、直近5つのコミットを対象にする場合は、HEAD~5を指定します。
git rebase -i HEAD~5このコマンドを実行すると、設定されているデフォルトエディタ(通常はVim)が開き、以下のような内容が表示されます。
pick 1a2b3c4 コミットA
pick 5d6e7f8 コミットB
pick 9g0h1i2 コミットC
pick 3j4k5l6 コミットD
pick 7m8n9o0 コミットE
# Rebase 1a2b3c4..7m8n9o0 onto 1a2b3c4 (5 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to re-use commit message
# . and also the original commit date and author.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here, that commit will be dropped.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out主要なコマンドとその使い方
エディタに表示されるコミットリストの各行の先頭にあるコマンドを編集することで、様々な操作を実行できます。以下に主要なコマンドを説明します。
pick (p): コミットをそのまま採用
デフォルトのオプションです。コミットの内容とメッセージをそのまま維持します。
pick 1a2b3c4 コミットAreword (r): コミットメッセージを編集
コミットの内容は維持しつつ、メッセージを修正したい場合に使用します。pickをrewordに変更してエディタを保存すると、そのコミットのメッセージ編集画面が再度開きます。
reword 1a2b3c4 コミットAedit (e): コミットの内容を修正
コミットの内容そのもの(ファイル変更)を修正したり、コミットを分割したい場合に使用します。editを指定すると、rebaseはそのコミットの適用後に一時停止します。ここでgit addやgit commit --amend、git resetなどを使って変更を加え、git rebase --continueで再開します。
edit 1a2b3c4 コミットAsquash (s): 前のコミットとまとめる
現在のコミットを、その直前のコミットに統合します。統合後、新しいコミットメッセージを編集する画面が表示され、両方のコミットメッセージを結合したり、新しいメッセージを作成したりできます。
pick 1a2b3c4 コミットA
squash 5d6e7f8 コミットB # コミットBがコミットAに統合されるfixup (f): 前のコミットとまとめる(メッセージ破棄)
squashと似ていますが、現在のコミットのメッセージを破棄し、前のコミットのメッセージをそのまま使用します。小さな修正を前のコミットに含めたいが、新しいメッセージは不要な場合に便利です。
pick 1a2b3c4 コミットA
fixup 5d6e7f8 コミットB # コミットBがコミットAに統合され、Bのメッセージは破棄されるdrop (d): コミットを削除
不要なコミットを履歴から完全に削除します。行を削除するのと同じ効果があります。
pick 1a2b3c4 コミットA
drop 5d6e7f8 コミットB # コミットBが削除されるこれらのコマンドを適切に組み合わせることで、開発中のブランチ履歴を劇的に改善し、プルリクエスト提出前にクリーンな状態に保つことができます。
Rebase中のコンフリクト解決

Rebaseはコミットを一つずつ再適用していくプロセスであるため、元のベースと新しいベースの間で変更が競合する場合、コンフリクト(衝突)が発生する可能性があります。コンフリクトはGitを使う上で避けられないものであり、適切に解決する方法を学ぶことは非常に重要です。
コンフリクトが発生しても慌てる必要はありません。Gitは親切にどのファイルでコンフリクトが起きているかを教えてくれます。落ち着いて指示に従いましょう。
コンフリクト発生時の流れ
rebase中にコンフリクトが発生すると、Gitはrebaseプロセスを一時停止し、以下のようなメッセージを表示します。
...
Applying: コミットメッセージ
Using index info to reconstruct a base tree...
M ファイル名.txt
Falling back to patching base and 3-way merge...
Auto-merging ファイル名.txt
CONFLICT (content): Merge conflict in ファイル名.txt
error: could not apply 1a2b3c4... コミットメッセージ
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".このメッセージは、ファイル名.txtでコンフリクトが発生したこと、そしてそれを解決してgit addし、git rebase --continueでrebaseを続行するように指示しています。
コンフリクトの解決手順
コンフリクトの解決は、以下の3つのステップで行います。
1. コンフリクトファイルの特定と編集
git statusコマンドを実行すると、コンフリクトしているファイルを確認できます。
git status
# On branch feature
# You are currently rebasing branch 'feature' on 'main'.
# (fix conflicts and run "git rebase --continue")
# (use "git rebase --skip" to skip this patch)
# (use "git rebase --abort" to check out the original branch)
#
# Unmerged paths:
# (use "git add <file>..." to mark resolution)
#
# both modified: ファイル名.txt
# no changes added to commit (use "git add" and/or "git commit -a")コンフリクトしているファイルを開くと、以下のような特殊なマーカーが表示されています。
<<<<<<< HEAD
// 現在のブランチ (feature) の変更
int value = 10;
=======
// rebase対象のブランチ (main) の変更
int value = 20;
>>>>>>> 1a2b3c4 (コミットハッシュ)<<<<<<< HEADから=======までが現在のブランチの変更、=======から>>>>>>> コミットハッシュまでがrebase対象のブランチ(この例ではmainのそのコミット)の変更です。これらを適切に修正し、マーカーをすべて削除します。
2. 解決済みの変更をステージング
ファイルを修正したら、その変更をステージングエリアに追加します。
git add ファイル名.txt複数のファイルがコンフリクトしている場合は、すべてのファイルを修正し、git addする必要があります。
3. Rebaseの続行
すべてのコンフリクトを解決し、ファイルをステージングしたら、rebaseプロセスを続行します。
git rebase --continueもし途中でrebaseを中止したい場合は、git rebase --abortを実行すれば、rebase開始前の状態に戻すことができます。
コンフリクトの解決は、Gitのスキルを向上させる上で避けて通れない道です。何度も経験することで、そのプロセスに慣れ、効率的に対応できるようになります。
チーム開発におけるRebaseの注意点

Git rebaseは強力なツールですが、その強力さゆえに、特にチーム開発においては慎重な使用が求められます。rebaseは履歴を書き換えるため、共有済みのブランチに対して不用意にrebaseを行うと、他の開発者の作業に深刻な影響を与える可能性があります。
ここでは、チームでrebaseを利用する際の最も重要な注意点と、安全な運用方法について解説します。
「公開された履歴をRebaseしない」という鉄則
Git rebaseを使用する上で最も重要なルールは、「既にリモートリポジトリにプッシュされ、他の開発者が参照しているブランチの履歴をrebaseしない」というものです。もし公開されたブランチをrebaseして履歴を書き換えてしまうと、他の開発者がそのブランチをpullしようとした際に、自身のローカル履歴とリモート履歴の間に不整合が生じ、複雑なコンフリクトや作業の混乱を招きます。
具体的には、rebase後のブランチを強制プッシュ (git push --force または git push --force-with-lease) しなければリモートに反映できませんが、これは他の開発者の履歴と食い違うため、絶対に行ってはいけません。
このルールは、チームのワークフローとコードの整合性を維持するために不可欠です。
安全なRebaseの運用方法
では、チーム開発でrebaseを安全に利用するにはどうすればよいでしょうか?
1. ローカルの個人ブランチのみでRebaseする
自身のローカル環境で作成し、まだリモートにプッシュしていない、あるいは他の誰も参照していないフィーチャーブランチであれば、自由にrebaseして履歴を整理できます。プルリクエストを出す前に、この方法で履歴をクリーンアップするのが理想的です。
2. プルリクエスト(PR)前にベースブランチを最新化する
プルリクエストを出す直前に、自分のフィーチャーブランチをmainブランチ(またはターゲットとなるベースブランチ)の最新状態にrebaseします。これにより、PR提出時のコンフリクトを最小限に抑え、レビューアにとっても変更内容が分かりやすい、直線的な履歴を提供できます。
git checkout feature-branch
git fetch origin
git rebase origin/mainこの操作の後、必要であればgit push --force-with-leaseでリモートブランチを更新しますが、これはあくまで自分が唯一の作業者であるブランチに限ります。
3. チーム内でRebaseポリシーを確立する
チーム全体でGitの運用ルールを明確にすることが重要です。例えば、「プルリクエストのマージは常にSquash Mergeで行う」「Featureブランチは個人作業中にのみrebaseを許可する」といったルールを定めることで、混乱を避けることができます。
これらの注意点を守ることで、rebaseのメリットを享受しつつ、チーム開発の安定性を損なうことなく作業を進めることができます。
よくある疑問とその解決策
Git rebaseは強力なツールであると同時に、複雑さも伴うため、多くの開発者が疑問や問題に直面します。ここでは、rebaseに関してよくある疑問とその解決策をまとめました。これらのQ&Aを通じて、rebaseへの理解をさらに深め、より自信を持って使いこなせるようになりましょう。
Q1: Rebaseを途中でやめたい場合はどうすればいいですか?
A: Rebase中に問題が発生したり、計画を変更したくなったりした場合、いつでもgit rebase --abortコマンドでrebaseを中止できます。このコマンドを実行すると、rebaseを開始する前の状態にブランチが戻されます。安全に元の状態に戻れるため、安心してrebaseを試すことができます。
git rebase --abortQ2: Rebase後にコミット履歴が消えてしまったように見えます。どうすれば元のコミットに戻れますか?
A: Rebaseによってコミットのハッシュ値が変わるため、元のコミットが履歴から見えなくなることがあります。しかし、Gitは変更をすぐに破棄するわけではありません。git reflogコマンドを使うと、Gitが記録している操作履歴(reflog)を確認でき、rebase前のコミットハッシュを見つけることができます。
git reflogreflogに表示されるrebase前のコミットハッシュ(例: HEAD@{1}や特定のコミットID)を使って、git reset --hard <コミットハッシュ>を実行すれば、元の状態に戻すことができます。これはrebaseで失敗した際に非常に役立つリカバリー手段です。
Q3: git push --forceとgit push --force-with-leaseの違いは何ですか?
A: どちらもリモートリポジトリの履歴を強制的に上書きしますが、安全性に大きな違いがあります。
git push --force: 無条件にリモートブランチを上書きします。たとえ他の誰かがその間にリモートブランチにプッシュしていたとしても、その変更は失われます。非常に危険なコマンドです。
git push --force-with-lease: リモートブランチが、最後にローカルで取得した状態から変更されていない場合にのみ、上書きを許可します。もし他の開発者がその間にリモートブランチを更新していた場合、プッシュは失敗し、意図しない変更の上書きを防ぎます。--forceよりもはるかに安全なオプションであり、公開されたブランチに対してやむを得ず強制プッシュする場合に推奨されます(ただし、基本的には公開ブランチへの強制プッシュは避けるべきです)。
Q4: RebaseとMerge、どちらを使うべきか迷います。
A: これはGitユーザー永遠のテーマとも言えますが、一般的なガイドラインは以下の通りです。
- Rebaseの利用シーン:
- まだ公開されていないローカルブランチの履歴を整理・クリーンアップする時。
- プルリクエストを出す前に、フィーチャーブランチを最新のベースブランチに追従させ、コンフリクトを事前に解決する時。
- 直線的で分かりやすいコミット履歴を維持したい時。
- Mergeの利用シーン:
- 既に公開されているブランチ(例:
mainや共有フィーチャーブランチ)を統合する時。 - ブランチが分岐し、それが統合されたという履歴を明示的に残したい時。
- 履歴の書き換えを避けたい時。
- 既に公開されているブランチ(例:
多くのチームでは、フィーチャーブランチはrebaseで整理し、mainブランチへの統合はマージコミットを残す「マージ」または「スクワッシュマージ」を使うというハイブリッドな戦略を採用しています。
まとめ:クリーンなGit履歴の重要性
これまでに、Git rebaseの基本概念からインタラクティブrebaseの具体的な使い方、コンフリクトの解決、そしてチーム開発における注意点まで、幅広く解説してきました。rebaseは、その特性を理解し、適切に利用することで、開発効率を大きく向上させる強力なツールです。
クリーンで分かりやすいGit履歴は、単に見栄えが良いだけでなく、チーム開発におけるコミュニケーションと効率の向上に直結します。
- コードレビューの効率化: 意味のある単位でまとめられたコミットは、レビューアが変更内容を理解しやすくなります。
- バグ修正・機能追加の容易化: 特定の変更がどのコミットで行われたかを素早く特定でき、問題の切り分けや過去の機能追加・変更の経緯を追跡しやすくなります。
- 新規メンバーのオンボーディング: 過去の履歴が整理されていることで、新しいメンバーがプロジェクトの歴史や変更の意図を把握しやすくなります。
2026年現在も、Gitはソフトウェア開発の現場で不可欠なツールであり続けています。rebaseをマスターし、より質の高い開発プロセスを実践していきましょう。
Git Rebaseを使いこなし、あなたの開発ワークフローを次のレベルへ。
このガイドが、あなたがより効率的で、より協調的な開発者になるための一助となれば幸いです。ぜひ今日からrebaseを実践し、そのメリットを実感してください。