Git でコミットを巻き戻すとは?reset と revert を使い分ける方法

git icon
Git

こんにちは、とまだです。

Git で開発していて「あのコミットまで戻したい」と思ったことはありませんか?

バグを直そうとしたら余計にひどくなってしまった。 新機能を試したけど、やっぱり前の状態がよかった。

そんなとき、どうやって過去のコミットに戻ればいいのか分からず困ってしまいますよね。

今回は、Git で特定のコミットまで戻る方法として git resetgit revert の使い分けを、実例を交えながら解説します。

Git のコミット履歴は時系列の記録

Git のコミット履歴は、まるで日記のように時系列で記録されています。

今日の変更、昨日の変更、一昨日の変更... すべてが順番に積み重なっているんです。

そして Git の素晴らしいところは、いつでも過去の状態に戻れること。

例えば、以下のようなコミット履歴があるとします。

# git log --oneline で履歴を確認
a1b2c3d (HEAD) バグ修正を試みた
e4f5g6h 新機能を追加
i7j8k9l リファクタリング実施
m1n2o3p 初期実装

最新のコミット(a1b2c3d)でバグ修正を試みたものの、かえって動作がおかしくなってしまった。

こんなとき「新機能を追加した時点(e4f5g6h)まで戻したい」と思うのは自然なことです。

reset と revert、2つの巻き戻し方法

Git で過去のコミットに戻る方法は主に2つあります。

git reset: 履歴そのものを巻き戻す git revert: 変更を打ち消す新しいコミットを作る

どちらを使うべきかは、状況によって変わります。

git reset:履歴を書き換える強力な方法

git reset は、まるでタイムマシンのように履歴を巻き戻します。

# e4f5g6h(新機能を追加)まで戻る
git reset --hard e4f5g6h

実行すると、最新のコミットが e4f5g6h になります。 a1b2c3d のコミットは、まるで最初から存在しなかったかのように消えてしまうんです。

でも、ここで注意が必要です。

もしすでにリモートリポジトリにプッシュしていた場合、他のメンバーと履歴が食い違ってしまいます。

チーム開発では大きな混乱を招く可能性があるので、個人で作業しているブランチでのみ使うのが安全です。

git revert:履歴を残したまま変更を取り消す

一方、git revert は過去の変更を「なかったこと」にする新しいコミットを作ります。

# a1b2c3d の変更を取り消す
git revert a1b2c3d

実行すると、以下のような履歴になります。

x9y8z7w (HEAD) Revert "バグ修正を試みた"
a1b2c3d バグ修正を試みた
e4f5g6h 新機能を追加
i7j8k9l リファクタリング実施
m1n2o3p 初期実装

履歴は残ったまま、a1b2c3d の変更だけが打ち消されました。

チーム開発では、こちらの方が安全です。 誰が見ても「あの変更を取り消したんだな」ということが分かりますから。

実際の使い分けはどうする?

では、実際にはどう使い分ければいいのでしょうか。

個人ブランチで試行錯誤している場合

まだ誰にも共有していない個人のブランチで作業している。 色々試してみたけど、うまくいかないから最初からやり直したい。

こんなときは git reset --hard が便利です。

# 作業を始める前の状態に戻す
git reset --hard origin/main

履歴がスッキリして、きれいな状態から再スタートできます。

すでにチームで共有しているブランチの場合

main ブランチや develop ブランチなど、チーム全体で使っているブランチ。 リリース後に重大なバグが見つかってしまった。

こんなときは必ず git revert を使います。

# 問題のあるコミットを特定して取り消す
git revert <問題のコミットハッシュ>
git push origin main

履歴に「このコミットを取り消した」という記録が残るので、後から振り返ったときにも経緯が分かります。

よくある失敗と対処法

コミットハッシュを間違えてしまった

焦って作業していると、コミットハッシュを打ち間違えることがあります。

# まず落ち着いて履歴を確認
git log --oneline -10

# グラフ表示でより分かりやすく
git log --graph --oneline -10

コミットハッシュは最初の7文字だけでも大丈夫です。 でも、確実にするならコピー&ペーストを使いましょう。

reset で大事な変更が消えてしまった

git reset --hard を実行したら、まだコミットしていない変更が全部消えてしまった...

実は、こんなときのために事前に保存しておく方法があります。

# 作業中の変更を一時保存
git stash

# reset を実行
git reset --hard <コミットハッシュ>

# 必要なら一時保存した変更を戻す
git stash pop

revert でコンフリクトが発生した

複数のコミットで同じファイルを編集していると、revert 時にコンフリクトが起きることがあります。

# コンフリクトが発生
git revert <コミットハッシュ>
# エラー: マージコンフリクトが発生しました

# コンフリクトを解決
# 1. エディタでファイルを開いて修正
# 2. 修正が終わったら
git add <修正したファイル>
git revert --continue

コンフリクトは避けられないこともありますが、落ち着いて対処すれば大丈夫です。

チーム開発で気をつけたいポイント

コミュニケーションを大切に

履歴を変更する前に、必ずチームメンバーに伝えましょう。

「main ブランチの昨日のコミットに問題があったので、revert します」

こんな一言があるだけで、混乱を防げます。

ブランチ戦略を明確に

個人の feature ブランチでは reset を使ってもOK。 共有ブランチでは必ず revert を使う。

こんなルールを決めておくと、迷わずに済みます。

コミットメッセージを丁寧に

revert する際のコミットメッセージは、後から見ても分かるように書きましょう。

# 良い例
git revert -m "APIのレスポンス形式変更によるバグを修正するため、コミット a1b2c3d を取り消し"

# 悪い例
git revert -m "バグったので戻します"

まとめ

Git で特定のコミットまで戻る方法として、git resetgit revert を紹介しました。

個人作業なら reset でスッキリと。 チーム開発なら revert で安全に。

この使い分けを覚えておけば、どんな状況でも適切に対処できます。

Git の履歴操作は最初は怖く感じるかもしれません。 でも、正しい使い方を知っていれば、開発の強い味方になってくれます。

まずは個人のブランチで練習してみて、慣れてきたら実務で活用してみてください。

共有:

著者について

とまだ

とまだ

フルスタックエンジニア

Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。

著者の詳細を見る →