はじめに
「コードを編集したけど元に戻したい」「直前のコミットを取り消したい」「共有済みのコミットを安全に打ち消したい」。Gitを使った開発では、このような変更取り消しの場面に頻繁に遭遇します。
しかし、Gitには変更取り消しのためのコマンドが複数存在し、使い分けに悩む方も多いのではないでしょうか。git restore、git reset、git revertはそれぞれ異なる目的と影響範囲を持ち、状況に応じた適切な選択が求められます。
本記事では、Gitの変更取り消しコマンドを体系的に解説します。この記事を読み終えると、以下のことができるようになります。
git restoreで作業ツリーやステージングエリアの変更を取り消せるgit resetの3つのモード(soft/mixed/hard)を理解し、コミットを取り消せるgit revertで共有済みコミットを安全に打ち消せる- 状況に応じて最適な変更取り消し方法を選択できる
実行環境と前提条件
本記事の内容は、以下の環境で動作確認を行っています。
| 項目 | 要件 |
|---|---|
| Git | 2.40以上 |
| OS | Windows 10/11、macOS 12以上、Ubuntu 22.04以上 |
| ターミナル | コマンドプロンプト、PowerShell、Terminal.app、bash等 |
| エディタ | VS Code推奨 |
前提条件として、以下の知識があることを想定しています。
- コマンドライン操作の基礎知識(
cd、ls/dir、mkdir等) - テキストエディタの基本操作
- Gitの基本コマンド(
git init、git add、git commit、git status)の理解
Git変更取り消しコマンドの概要
Gitで変更を取り消すには、主に以下の3つのコマンドを使用します。
| コマンド | 主な用途 | 影響範囲 | 履歴の変更 |
|---|---|---|---|
git restore |
作業ツリー・ステージングエリアの変更取り消し | ファイル単位 | なし |
git reset |
コミットの取り消し、HEADの移動 | リポジトリ全体 | あり |
git revert |
コミットの打ち消し(新規コミット作成) | 指定コミット | なし(追加のみ) |
これらのコマンドを正しく使い分けることで、安全かつ効率的に変更を取り消すことができます。
使い分けの基本方針
どのコマンドを使うべきかは、以下の判断基準で決定します。
| 状況 | 推奨コマンド |
|---|---|
| ファイルの編集を破棄したい(コミット前) | git restore |
| ステージングを取り消したい | git restore --staged |
| 直前のコミットをやり直したい(ローカルのみ) | git reset |
| 複数のコミットを取り消したい(ローカルのみ) | git reset |
| 共有済みのコミットを取り消したい | git revert |
| 特定のコミットの変更のみを打ち消したい | git revert |
git restore - 作業ツリーとステージングエリアの変更取り消し
git restoreは、Git 2.23で導入された比較的新しいコマンドです。作業ツリー(ワーキングディレクトリ)やステージングエリア(インデックス)のファイルを、特定の状態に復元するために使用します。
作業ツリーの変更を取り消す
ファイルを編集したものの、その変更を破棄して直前のコミット状態に戻したい場合に使用します。
|
|
実行例を見てみましょう。
|
|
app.jsの変更が取り消され、index.htmlの変更のみが残っています。
ステージングエリアの変更を取り消す
git addでステージングしたファイルをアンステージ(ステージング取り消し)する場合は、--stagedオプションを使用します。
|
|
実行例を見てみましょう。
|
|
app.jsがステージングエリアから作業ツリーに戻りました。ファイルの内容自体は変更されていません。
作業ツリーとステージングエリアを同時に取り消す
--stagedと--worktreeを組み合わせることで、両方を同時に取り消すことができます。
|
|
特定のコミットからファイルを復元する
--sourceオプションを使用すると、特定のコミットからファイルを復元できます。
|
|
実行例を見てみましょう。
|
|
復元されたファイルは作業ツリーに配置され、未ステージの変更として扱われます。
git restoreの注意点
git restoreを使用する際は、以下の点に注意してください。
| 注意点 | 説明 |
|---|---|
| 変更の消失 | 作業ツリーの変更を取り消すと、その変更は完全に失われます |
| 復元不可 | git restoreで取り消した変更は、通常の方法では復元できません |
| 未追跡ファイル | 未追跡ファイル(新規作成ファイル)には影響しません |
重要な変更がある場合は、取り消す前にgit stashで一時保存することを検討してください。
git reset - コミットの取り消しとHEADの移動
git resetは、現在のブランチのHEADを指定したコミットに移動させるコマンドです。コミットの取り消しや履歴の巻き戻しに使用します。
git resetの3つのモード
git resetには3つの主要なモードがあり、それぞれ影響範囲が異なります。
| モード | HEAD | ステージングエリア | 作業ツリー | 用途 |
|---|---|---|---|---|
--soft |
移動 | 維持 | 維持 | コミットのやり直し |
--mixed(デフォルト) |
移動 | リセット | 維持 | ステージングのやり直し |
--hard |
移動 | リセット | リセット | 変更の完全な破棄 |
git reset –soft(コミットのやり直し)
--softモードは、HEADのみを移動させ、ステージングエリアと作業ツリーはそのまま維持します。コミットをやり直したい場合に最適です。
|
|
実行例を見てみましょう。
|
|
変更内容はステージングエリアに残っているため、修正してから再度コミットできます。
git reset –mixed(デフォルト)
--mixedモードは、HEADとステージングエリアをリセットし、作業ツリーはそのまま維持します。オプションを省略した場合はこのモードが適用されます。
|
|
実行例を見てみましょう。
|
|
変更内容は作業ツリーに残っていますが、ステージングは解除されています。
git reset –hard(変更の完全な破棄)
--hardモードは、HEAD、ステージングエリア、作業ツリーのすべてをリセットします。すべての変更が失われるため、最も注意が必要なモードです。
|
|
実行例を見てみましょう。
|
|
コミットも作業ツリーの変更もすべて失われました。
git resetの実践的なユースケース
直前のコミットメッセージを修正したい
|
|
なお、直前のコミットメッセージの修正だけであれば、git commit --amendを使う方法もあります。
複数のコミットを1つにまとめたい
|
|
ステージングをやり直したい
|
|
git resetの注意点
| 注意点 | 説明 |
|---|---|
| 履歴の改変 | git resetは履歴を改変するため、プッシュ済みのコミットには使用しないでください |
| 強制プッシュが必要 | リモートにプッシュ済みの場合、git push --forceが必要になります |
| チームへの影響 | 共有ブランチで使用すると、他のメンバーに影響を与えます |
--hardの危険性 |
変更が完全に失われるため、実行前に必ず確認してください |
git revert - 安全なコミットの打ち消し
git revertは、指定したコミットの変更を打ち消す新しいコミットを作成するコマンドです。履歴を改変せずに変更を取り消すため、共有リポジトリでも安全に使用できます。
基本的な使い方
|
|
実行例を見てみましょう。
|
|
元のコミット(abc1234)は履歴に残ったまま、その変更を打ち消す新しいコミット(jkl3456)が作成されました。
複数のコミットを打ち消す
複数のコミットを連続して打ち消す場合は、範囲指定や個別指定が可能です。
|
|
マージコミットを打ち消す
マージコミットを打ち消す場合は、どちらの親を基準にするかを-mオプションで指定する必要があります。
|
|
-m 1は、マージ先(通常はmainブランチ)を基準にすることを意味します。
git revertのオプション
| オプション | 説明 |
|---|---|
--no-commit / -n |
コミットを作成せず、変更のみ適用する |
--no-edit |
エディタを開かずにデフォルトメッセージでコミット |
--edit / -e |
コミットメッセージを編集する(デフォルト) |
-m <親番号> |
マージコミットの打ち消し時に親を指定する |
コンフリクトが発生した場合
git revert実行時にコンフリクトが発生することがあります。
|
|
コンフリクト解消の手順は以下のとおりです。
|
|
git revertの実践的なユースケース
本番環境に影響を与えた変更を素早く取り消す
|
|
複数の修正をまとめて打ち消す
|
|
3つのコマンドの使い分け早見表
状況に応じた最適なコマンドを選択するための早見表です。
| 状況 | コマンド | 具体例 |
|---|---|---|
| ファイルの編集を破棄したい | git restore <ファイル> |
間違った編集を取り消す |
| ステージングを取り消したい | git restore --staged <ファイル> |
git addを取り消す |
| 直前のコミットをやり直したい | git reset --soft HEAD~1 |
コミットメッセージを変更 |
| コミットを取り消して変更も破棄したい | git reset --hard HEAD~1 |
不要なコミットを完全削除 |
| プッシュ済みコミットを取り消したい | git revert <コミット> |
本番のバグ修正を打ち消し |
| マージを取り消したい(ローカル) | git reset --hard HEAD~1 |
ローカルでのマージをやり直す |
| マージを取り消したい(リモート済み) | git revert -m 1 <コミット> |
共有済みマージを打ち消す |
ローカルのみ vs リモート共有済み
最も重要な判断基準は、「変更がリモートリポジトリにプッシュ済みかどうか」です。
| 状態 | 推奨コマンド | 理由 |
|---|---|---|
| ローカルのみ | git reset |
履歴を自由に変更可能 |
| リモート共有済み | git revert |
履歴を改変せず安全に取り消し可能 |
リモートにプッシュ済みのコミットに対してgit resetを使用すると、git push --forceが必要になり、他のチームメンバーに影響を与える可能性があります。
実践演習:変更取り消しの練習
実際に手を動かして、各コマンドの動作を確認しましょう。
準備:練習用リポジトリの作成
|
|
演習1:git restoreの練習
|
|
期待される結果:app.jsの変更が取り消され、元の内容に戻ります。
演習2:git reset –softの練習
|
|
期待される結果:コミットが取り消され、変更はステージングエリアに残っています。
演習3:git revertの練習
|
|
期待される結果:新しい打ち消しコミットが作成され、app.jsは元の状態に戻ります。
トラブルシューティング
git reset –hardで消した変更を復元したい
git reflogを使用すると、過去のHEAD位置を確認できます。
|
|
ただし、reflogの記録は一定期間(デフォルト90日)で削除されるため、早めに対処してください。
git revert中にコンフリクトが発生して中断したい
|
|
どのコマンドを使うべきかわからない
以下のフローチャートを参考にしてください。
flowchart TD
A[変更を取り消したい] --> B{コミット前の変更?}
B -->|Yes| C[git restore を使用]
B -->|No| D{ローカルのコミット?}
D -->|Yes| E[git reset を使用]
D -->|No| F{リモートにプッシュ済み?}
F -->|Yes| G[git revert を使用]まとめ
本記事では、Gitの変更取り消しコマンドであるgit restore、git reset、git revertについて解説しました。
| コマンド | 用途 | 履歴への影響 | 安全性 |
|---|---|---|---|
git restore |
作業ツリー・ステージングの取り消し | なし | 高い |
git reset --soft |
コミットの取り消し(変更維持) | あり | 中程度 |
git reset --mixed |
コミット+ステージングの取り消し | あり | 中程度 |
git reset --hard |
すべての取り消し | あり | 低い |
git revert |
打ち消しコミットの作成 | なし(追加のみ) | 高い |
最も重要なポイントは、リモートにプッシュ済みのコミットにはgit revertを使用することです。git resetは履歴を改変するため、ローカルでの作業にのみ使用してください。
これらのコマンドを適切に使い分けることで、開発中のミスを素早く修正し、チーム開発においても安全に変更を取り消すことができるようになります。