間違えてコミットしてしまったときの取り消し方は、「まだpushしていないか」「変更内容を残したいか」で決まります。まず下の早見表で自分の状況に合うコマンドを選び、詳しい違いは各章で確認してください。
| やりたいこと | push前/後 | コマンド |
|---|---|---|
| 直前のコミットのメッセージや内容を直したい | push前 | git commit --amend |
| 直前のコミットを取り消し、変更はステージングに残す | push前 | git reset --soft HEAD~1 |
| 直前のコミットを取り消し、変更もステージングから外す(ファイルは残る) | push前 | git reset HEAD~1 |
| 直前のコミットを変更ごと捨てる | push前 | git reset --hard HEAD~1 |
| push済みのコミットを取り消す | push後 | git revert <コミットID> → git push |
| resetしてしまったのを元に戻す | どちらでも | git reflog → git reset --hard HEAD@{1} |
HEAD~1はHEAD^と書いても同じ意味です(1つ前のコミット)。迷ったら、履歴を書き換えないgit revertを選べば他の人の作業を壊すことはありません。
1. Gitのコミット取り消しの基本
Gitでコミットを取り消す方法には、主に以下の2つがあります。
- git reset
- コミットを取り消し、履歴から削除します。
- git revert
- コミットを取り消す新しいコミットを作成し、履歴を保持します。
これらの方法はそれぞれ異なる用途に適しており、状況に応じて使い分ける必要があります。
2. git resetを使ったコミットの取り消し
git resetコマンドは、特定のコミットを取り消し、そのコミット以降の変更を履歴から削除します。この方法は、ローカルリポジトリでの作業中に誤ったコミットを取り消したい場合に便利です。
2.1 git resetの種類
- --soft: コミットを取り消し、変更をステージングエリアに残します。
- --mixed: コミットを取り消し、変更をワーキングディレクトリに残します(デフォルト)。
- --hard: コミットを取り消し、変更を完全に破棄します。
2.2 例: git resetの使用
以下のコマンドは、最新のコミットを取り消し、変更をステージングエリアに残します。
git reset --soft HEAD~1このコマンドを実行すると、最新のコミットが取り消され、変更内容はステージングエリアに残ります。これにより、再度コミットを行うことができます。
もし、変更を完全に破棄したい場合は、以下のコマンドを使用します。
git reset --hard HEAD~1このコマンドは、最新のコミットを取り消し、変更を完全に破棄します。注意が必要なのは、この操作は元に戻せないため、慎重に行う必要があります。
3. git revertを使ったコミットの取り消し
git revertコマンドは、指定したコミットの変更を打ち消す新しいコミットを作成します。この方法は、特にリモートリポジトリにプッシュした後のコミットを取り消す際に推奨されます。なぜなら、git revertは履歴を保持し、他の開発者との協力を妨げないからです。
3.1 git revertの使用方法
以下のコマンドは、特定のコミットを取り消すために使用します。
git revert <commit_hash>ここで、<commit_hash>は取り消したいコミットのハッシュ値です。例えば、以下のように実行します。
git revert 1a2b3c4dこのコマンドを実行すると、指定したコミットの変更を打ち消す新しいコミットが作成されます。これにより、履歴は保持され、他の開発者にも影響を与えません。
4. どちらの方法を選ぶべきか?
- ローカルでの作業中
- まだリモートにプッシュしていない場合は、
git resetを使用してコミットを取り消すことができます。
- まだリモートにプッシュしていない場合は、
- リモートにプッシュした後
- 他の開発者と共有しているリポジトリの場合は、
git revertを使用して履歴を保持しつつ変更を取り消すことが推奨されます。
- 他の開発者と共有しているリポジトリの場合は、
5. 具体的なシナリオと手順
5.1 シナリオ1: 誤ったコミットを取り消す
- 最新のコミットを取り消したい場合:
- ステージングエリアに変更を残したい場合
git reset --soft HEAD~1
- 変更を完全に破棄したい場合
git reset --hard HEAD~1
- ステージングエリアに変更を残したい場合
- 特定のコミットを取り消したい場合(リモートにプッシュ済み)
git revert <commit_hash>
5.2 シナリオ2: 複数のコミットを取り消す
複数のコミットを取り消す場合、git resetを使用することができますが、注意が必要です。以下のコマンドは、最新の3つのコミットを取り消します。
git reset --hard HEAD~3ただし、これにより履歴が変更されるため、リモートにプッシュした後は使用しないでください。
複数のコミットを安全に取り消すためには、git revertを使用します。以下のように、複数のコミットを指定して取り消すことができます。
git revert <commit_hash_1> <commit_hash_2>5.3 シナリオ3: push済みのコミットを取り消す
リモートにpushしたコミットは、git revertで「打ち消すコミット」を作ってからpushします。履歴を書き換えないので、他の人がすでにpullしていても問題になりません。
# 取り消したいコミットのIDを確認する
git log --oneline
# 打ち消しコミットを作成してpushする
git revert 1a2b3c4
git push origin mainマージコミットを取り消す場合は、どちらの親を基準に戻すかを-mで指定します。通常はマージ先のブランチ側(1番目の親)を指定します。
git revert -m 1 <マージコミットのID>自分しか使っていないブランチで、履歴ごと消したい場合に限り、git resetの後に強制pushする方法もあります。その場合は--forceではなく--force-with-leaseを使うと、他の人が追加したコミットを誤って上書きするのを防げます。
git reset --hard HEAD~1
git push --force-with-lease origin feature/my-branch共有ブランチの履歴を書き換えると、他の人のpushが「rejected」で失敗するようになります。そうなったときの対処はGit push時に「rejected」が出たときの解決方法にまとめています。
5.4 シナリオ4: 直前のコミットを修正する(git commit --amend)
コミットメッセージの誤字や、ファイルの入れ忘れであれば、取り消さずに直前のコミットを上書きするのが手早い方法です。
# メッセージだけ直す
git commit --amend -m "正しいコミットメッセージ"
# 入れ忘れたファイルを追加する(メッセージはそのまま)
git add forgotten_file.txt
git commit --amend --no-edit--amendはコミットを作り直す操作なので、コミットIDが変わります。push済みのコミットに使うと、resetと同じく強制pushが必要になるため、push前だけに使うのが安全です。
5.5 シナリオ5: 取り消しを取り消す(git reflog)
git reset --hardで消したコミットも、しばらくの間はgit reflogに記録が残っています。HEADの移動履歴から戻りたい地点を探して、そこへresetし直します。
git reflog
# 例:
# 3c4d5e6 HEAD@{0}: reset: moving to HEAD~1
# 9f8e7d6 HEAD@{1}: commit: ログイン画面を追加
# reset直前の状態に戻す
git reset --hard HEAD@{1}ただし、一度もコミットしていない作業中の変更はgit reset --hardで消えると戻せません。rebaseで消えたコミットも同じ方法で復元できます(Gitリベースで消えたコミットを復元する手順)。コミット全体ではなく特定のファイルだけを戻したい場合は、過去のコミットから特定のファイルだけ復元する方法が使えます。
6. 取り消し後の確認
コミットを取り消した後は、以下のコマンドで履歴を確認することができます。
git log
これにより、現在のコミット履歴を確認し、取り消しが正しく行われたかを確認できます。
7. まとめ
Gitで間違ったコミットを取り消す方法について解説しました。以下のポイントを押さえておくと、より安全にコミットを取り消すことができます。
git reset- ローカルでの作業中に使用し、履歴を変更します。
git revert- リモートにプッシュした後のコミットを取り消す際に使用し、履歴を保持します。
- 慎重に操作する
- 特に
--hardオプションを使用する際は、変更が完全に失われることを理解しておく必要があります。
- 特に
これらの手順を理解し、適切に使用することで、Gitをより効果的に活用し、開発プロセスをスムーズに進めることができます。
参考
- git-reset Documentation(Git公式)
- git-revert Documentation(Git公式)
- git-commit Documentation(Git公式、--amend)
- git-reflog Documentation(Git公式)