git rebaseを間違えた時の戻し方|実践的なリカバリ手順

git rebaseで失敗してコミット履歴がおかしくなった場合、git refloggit resetを組み合わせれば安全に戻せます。この記事では、rebase失敗時の3つのリカバリ方法と、各状況での使い分けを実装例とともに解説します。

git rebaseが失敗する主なケース

rebaseを戻す方法を学ぶ前に、どのような状況で失敗が起こるのかを理解することが重要です。

コンフリクトが発生して進められない

rebase中にマージコンフリクトが発生し、解決方法が分からない場合があります。この場合、rebaseを続行するか中止するかを判断する必要があります。

誤ったコミットを対象にしてしまった

rebase -iで対象範囲を間違えて指定し、予期しないコミットが書き換わってしまうケースです。

不要なコミットを削除してしまった

対話的rebaseで重要なコミットを誤って削除して、コミット履歴から消えてしまう状況です。

方法1:git reflogで履歴を確認して戻す(最も安全)

git reflogはGitの操作履歴を記録しており、rebase実行前の状態に戻すための最強ツールです。すべてのローカル操作が記録されているため、まずはこれを確認しましょう。

実装手順


# rebase実行前の状態を確認
git reflog

# 出力例:
# a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/feature
# d4e5f6g HEAD@{1}: rebase (continue): sample commit
# h8i9j0k HEAD@{2}: rebase (start): checkout main
# l1m2n3o HEAD@{3}: commit: feature branch setup

# rebase実行前に戻したい場合(例:HEAD@{3})
git reset --hard HEAD@{3}
  

上記のコマンドで、rebase前の状態に完全に戻ります。--hardオプションは作業ディレクトリとインデックスも同時にリセットするため、変更内容はすべて破棄されます。

よりシンプルな戻し方

どの時点に戻すかが不明な場合は、ORIG_HEADを使う方法もあります。


# rebase実行の直前の状態に戻す
git reset --hard ORIG_HEAD
  

ORIG_HEADは、危険な操作(rebasemerge、reset)の直前の状態を自動的に保存している特殊な参照です。

方法2:rebase中に中断する場合

rebase処理の途中でコンフリクトが発生し、「このrebaseは中止したい」と判断した場合は、以下のコマンドで中止できます。

rebaseの中止コマンド


# rebase処理を完全に中止して、実行前の状態に戻す
git rebase --abort
  

git rebase --abortは、rebase開始前の状態に完全に戻します。rebase中にコンフリクトが発生した場合、このコマンドで安全に中止できます。

実装例:コンフリクト時の処理フロー


# featureブランチをmainにrebaseしようとする
git rebase main

# コンフリクトが発生した場合の出力:
# error: could not apply a1b2c3d... commit message
# Resolve all conflicts manually, mark them as resolved with
# "git add/rm <conflicted_files>", then run "git rebase --continue".

# 判断ポイント:
# 1. コンフリクトを解決できる → 手動で修正して git add → git rebase --continue
# 2. このrebaseは不要 → git rebase --abort
  

方法3:rebase後に問題が判明した場合

rebaseが完了した後に、「このrebaseは間違っていた」と気付く場合があります。この場合もreflogで対応できます。

rebase完了後の戻し方


# 現在のブランチの操作履歴を詳細表示
git reflog

# 出力例:
# a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/feature
# d4e5f6g HEAD@{1}: rebase (continue): another commit
# h8i9j0k HEAD@{2}: rebase (start): checkout main
# l1m2n3o HEAD@{3}: commit: before rebase

# rebase前に戻す
git reset --hard HEAD@{3}

# 確認
git log --oneline
  

よくあるハマりポイント:pushしてしまった場合

rebaseしたブランチをリモートにpushしてしまった場合は、戻した後に強制pushが必要です。ただし、チーム開発ではこれは避けるべき操作です。


# ローカルで戻す
git reset --hard ORIG_HEAD

# 確認してから強制push(注意:チーム開発では要調整)
git log --oneline
git push origin feature --force-with-lease
  

--force-with-lease--forceより安全で、他の人が同じブランチにpushしていないかチェックしてから実行します。

方法4:特定のコミットだけを復元する場合

rebase中に特定のコミットが誤って削除された場合は、git cherry-pickで復元できます。

削除されたコミットの復元手順


# reflogで削除前のコミットハッシュを確認
git reflog

# 削除されたコミットを見つける(例:h8i9j0k)
git log h8i9j0k --oneline -10

# 現在のブランチに特定のコミットだけを追加
git cherry-pick h8i9j0k

# 複数のコミットを復元する場合
git cherry-pick h8i9j0k^..d4e5f6g
  

このアプローチは、削除されたコミット全体を復元する必要がない場合に有効です。

使うべき場面と使うべきでない場面

git rebaseを使うべき場面

  • 個人のfeatureブランチで、コミット履歴をきれいに整理したい
  • mainブランチの最新状態を取り込みつつ、直線的なコミット履歴を保ちたい
  • 対話的rebaseで不要なコミットをまとめたい

git rebaseを避けるべき場面

  • すでにリモートにpushされた公開ブランチ(チーム開発の共有ブランチ)
  • 複数人が同時に編集しているブランチ
  • コミット履歴の整理に不慣れな開発者が扱う場合(git mergeの方が安全)

参考資料

公式ドキュメント:git-reflogで、reflogの詳細な仕様を確認できます。

よくある質問

git reset --hardは作業ディレクトリも変更する完全なリセットです。--softはコミットだけを取り消し、変更内容はステージ領域に残します。rebaseから戻る場合は通常--hardを使います。

git reflogはブランチごとに独立した履歴を記録しています。戻したいブランチをチェックアウトしてからgit reflogを実行し、そのブランチの操作履歴を確認してください。

まとめ

  • git reflogで操作履歴を確認し、git reset --hardで確実に戻す
  • rebase中のコンフリクトはgit rebase --abortで中止できる
  • ORIG_HEADを使えば、直前の危険な操作前の状態に瞬時に戻せる
  • 公開ブランチへのrebaseは避け、個人ブランチでのみ使用する
  • 誤削除されたコミットはgit cherry-pickで個別復元も可能
K
AWS・Python・生成AIを専門とするソフトウェアエンジニア。AI・クラウド・開発ワークフローの実践ガイドを執筆しています。詳しく見る →