今回は、Gitで過去のコミットに戻る方法について解説します。
Gitを使っていると、こんな場面ありませんか?
- 以前の状態に戻したい
- バグが出たので正常な状態に戻したい
- 間違ったコミットをなかったことにしたい
- reset / revert の違いが分からない
結論から言うと、安全に戻すなら git revert、履歴ごと戻すなら git reset を使います
ただし、使い方を間違えると履歴が消える・チームに影響が出るので注意が必要です。
リポジトリにpushしたあとか、前かで対応が異なります。
この記事では、初心者の方でも分かるように「安全な方法 → 危険な方法 → 使い分け」の順で解説します。
Gitで過去のコミットに戻る方法(結論)
Gitで過去に戻る方法をまとめると、主に3つです。
| 方法 | コマンド | 安全性 | 特徴 |
|---|---|---|---|
| 元に戻す(履歴を残す) | git revert |
◎ 安全 | 打ち消しコミットを作る |
| 強制的に戻る | git reset |
△ 注意 | 履歴を書き換える |
| 一時的に戻る | git checkout |
○ | 状態を確認するだけ |
一番安全:git revert(おすすめ)
最も安全なのがgit revertです。
git revertを使うと、コミットした内容を打ち消すコミットが作れます。
特徴
- 履歴を消さない
- チーム開発でも安全
- push後でも使える
このような特徴があり、すでにpushしてしまっている場合は、他のチームメンバーが取得している可能性があるためrevertを使った方がいいです。
履歴を消したい場合は、チームメンバーに知らせた後に、後述するresetを使って、git push --forceしましょう。
使い方
git revert コミットID
例
git revert a1b2c3d
指定したコミットを打ち消す新しいコミットが作られます。
どういう仕組み?
A → B → C(現在)
↓
A → B → C → Cを打ち消すコミットDができる
現在の履歴に加えて、打ち消しコミットが作られます。
履歴はそのままなので、チームメンバーに取得されていても問題なくプッシュして大丈夫です。
履歴ごと戻す:git reset(注意)
git reset は強力ですが、注意が必要です。
resetを使うと、履歴も一緒に消すことができます。
特徴
このような特徴があります。
- コミットをなかったことにする
- 履歴が消える
- push後は基本NG
どういう仕組み?
A → B → C(現在)
↓ reset --hard HEAD~1 を実行
A → B(Cが消える)
このように実行すると、履歴自体が消えます。
コミット自体がなくなるため、プッシュ後の使用は控えた方がいいです。
これは、ほかのチームメンバーが既に取得していて、ローカルとリポジトリの差分が合わなくなる可能性があるためです。
他のメンバーがそのコミットをベースに作業を始めている場合、強制的に履歴を消すと、他の人の環境でpushやpullができなくなる(競合が多発する)原因になります。
ひとりだけで使っているGitリポジトリであれば問題ないです。
よく使う3種類
よく使う操作の3種類です。
① soft(履歴だけ戻す)
git reset --soft HEAD~1
- コミットだけ削除
- 変更内容は残る
直近の1つ分のコミット履歴だけ消して、ファイルの変更内容は残ります。
「コミットコメントを間違えた」・「コミット漏れがあった」というときに、筆者もよく使っています。
② mixed(よく使う)
git reset HEAD~1
- コミット削除
- ステージも解除
こちらは、先ほどの状態と同じですが、ステージエリアからファイルが解除されます。
完全にコミット前に戻して、変更内容を確認し直したり、修正するときに便利です。
③ hard(危険)
git reset --hard HEAD~1
--hardオプションを使うと、コミット内容とファイル自体が消えてしまいます。
そのため、本当に必要のないコミットのとき以外には使わない方が良いです。
もしreset --hardで消してはいけないものを消してしまったら、git reflog コマンドで操作履歴を確認し、元の状態に戻せる可能性があります。
諦める前に試してみてください。
注意点(重要)
最後に注意点です。
resetについては、push済みのコミットに使うと、開発メンバーのローカルと食い違いがでる可能性があります。
少人数の場合には、ヒアリングして問題ないか確認し使っても良いでしょう。
基本的には、push済みの場合にはrevertを使った方が安全です。
リポジトリにプッシュする前(チームで共有前)であれば使っても問題ないです。
一時的に戻る:git checkout
過去の状態を「確認したいだけ」ならgit checkoutを使いましょう。
git checkout コミットID
この操作をすると、下記の2点の状態になります。
- detached HEAD になる
- そのまま作業するとブランチに属さない
ブランチに属していないため、そのまま作業を進めるのはやめましょう。
確認などが終わったら、ブランチに戻って作業するようにします。
安全に使う方法
git checkout -b new-branch コミットID
checkout時に新しいブランチを作って、作業するのもありです。
こうすると、指定した「コミットID」のときの状態で、「new-branch」が作られます。
コミットIDの確認方法
戻したい箇所のコミットIDを確認する方法です。
まずは対象のコミットを確認します。
git log
短く表示したい場合はこちらです。
git log --oneline
実際にコマンドを使うと、このように左にコミットIDが記載されています。
% git log --oneline
db0f9e5 (HEAD -> merge_test1) Merge branch 'merge_test2' into merge_test1
4502ca6 (merge_test2) コンフリクトテスト
72d8825 マージテストコンフリクト
ca4defd (origin/main, merge_branch, main) マージテスト
63fb320 (test_branch) ファイルに新規のテスト行を追加
どれを使うべき?(使い分け)
最後に使い分けについてです。
簡単にまとめると、下記になります。
- とにかく安全に戻したい →
git revert - ローカルだけで履歴整理 →
git reset - 過去の状態を確認したい →
git checkout
履歴は残したまま、戻したい場合にはgit revertを使っていきましょう。
履歴を消したい場合には、コミットを既にプッシュしたかを確認し、していない場合はgit resetを使うようにしましょう。
既にpushしている場合でも、ほかのメンバーが取得していなかったらgit resetした後にgit push --forceするのもありです。
まとめ
今回はGitで過去のコミットに戻る方法を確認していきました。
既にpushしたかどうかを確認して、git revertとgit resetを使い分けましょう。
単純にコミット時点の内容を確認したい場合にはgit checkoutも有効です。
最終的に迷ったらrevertを使うのが安全です。

コメント