git statusを実行すると、いつの間にか触れていたり、変更が加わってしまったファイルが、ステージ前のファイルとして赤文字で表示されることがあります。

このようなステージ前のファイルの変更を取り消す方法についてです。
(別の言い方をすると、Changes not staged for commit: で表示されている特定のファイルを、Changes not staged for commit: の一覧から外す方法)
対象となるのが特定のファイルか、全てのファイルかで対応方法が異なります。
対応方法の早見表
ステージ前の変更を取り消す
| 内容 | 処理 |
|---|---|
| 特定のファイルの変更を取り消す | git checkout @ <ファイル名> |
| 複数のファイルの変更を取り消す | git checkout @ <ファイル名> <ファイル名> |
| 全てのファイルの変更を取り消す | git reset –hard @ |
ステージ前の特定のファイルの変更を取り消す
1つのファイルの変更を取り消す
git checkout で最新のコミット(@)とファイルパスを指定します。
ファイルパスはgit statusの表示内容のコピペで問題ありません。
git checkout @ <ファイルパス> @ は最新のコミットを表します。HEAD と同じです。
コミットを遡る方法
最新のコミットを@として、一つ前のコミットを指定するには^を。2つ前を指定するには^^を使います。
^の数だけ、コミットを遡ります。
| 記号 | 意味 |
|---|---|
| @ | 現在のコミット |
| @^ | 1つ前のコミット |
| @^^ | 2つ前のコミット |
| @^^^ | 3つ前のコミット |
コミットをたくさん遡る場合
3個ぐらいまでならわかりやすいですが、5個遡るとなると、@^^^^^ となって、正しいコミットを指しているのかわかりにくくなります。
その時は、 @~n を使うとわかりやすくなります。 n に遡りたい数値を入れます。例えば、@~3 なら3つ前のコミットになります。
| 記号 | 意味 |
|---|---|
| @ | 現在のコミット |
| @~1 | 1つ前のコミット(@^ と同じ) |
| @~3 | 3つ前のコミット (@^^^ と同じ) |
| @~7 | 7つ前のコミット |
実例
client.rbとroutes.rbの2つのファイルに変更があった(ステージ前である)ことをGitが教えてくれている場合に、routes.rbのファイルのみ変更を取り消す例です。
#状態を確認
$ git status
On branch aa
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/models/client.rb
modified: config/routes.rb
no changes added to commit (use "git add" and/or "git commit -a")
#ステージ前の変更を取り消す
$ git checkout config/routes.rb
Updated 1 path from the index
#状態を確認
$ git status
On branch aa
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/models/client.rb
no changes added to commit (use "git add" and/or "git commit -a")config/routes.rbのみ変更を取り消すことができました。ファイル自体を確認すれば変更内容が消えています。
複数のファイルの変更を取り消す
git checkout で最新のコミット(@)を指定した後に、変更を取り消したいファイルパスをスペース空けて記載していきます。
git checkout @ <ファイルパス> <ファイルパス>,,,ファイル名が1つでも間違っている場合はエラーになります。
$ git checkout @ app/models/client.rb routes.rb
error: pathspec 'routes.rb' did not match any file(s) known to git実例
client.rbとroutes.rbの2つのファイルに変更があった(ステージ前である)ことをGitが教えてくれている場合に、routes.rbのファイルのみ変更を取り消す例です。
#状態を確認
$ git status
On branch aa
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/models/client.rb
modified: config/routes.rb
no changes added to commit (use "git add" and/or "git commit -a")
#ステージ前の変更を取り消す(2ファイル)
$ git checkout @ app/models/client.rb config/routes.rb
Updated 2 paths from 28ae331
#状態を確認
$ git status
On branch aa
nothing to commit, working tree cleanステージ前の全てのファイルの変更を取り消す
ステージ前の全てのファイルの変更を取り消すにはcheckoutではなく、reset –hardを使います。
git reset --hard @git reset --hard はファイルの指定はできません。指定できるのはコミットのみです。
ファイルを指定するとエラーになります。
$ git reset --hard config/routes.rb
fatal: Cannot do hard reset with paths.git checkout は何をしているか?
git checkoutといえば、最もよく使うのはブランチの移動です。git checkout <ブランチ名>
ですが、ここでは、ブランチ名ではなくファイル名をしています。つまり、git checkout = ブランチを移動するものではありません。
git checkoutとは指定した内容にバージョン(gitのファイルのログ)を合わせるコマンドです。
git checkout <コミット> <ファイル名> のように対象のコミットとファイルを指定した場合は、そのコミットの状態(バージョン)にファイルの内容を合わせます。
コミットやファイルを指定せず、git checkout <ブランチ名> でブランチを指定した場合は、ファイルの内容をそのブランチのバージョンに合わせます。合わせて、現在位置を指すポインタ(HEAD)がそのブランチに移動します。
(参考)対応方法一覧
ステージ前の変更を取り消す
| 内容 | 処理 |
|---|---|
| 特定のファイルの変更を取り消す | git checkout @ <ファイル名> |
| 複数のファイルの変更を取り消す | git checkout @ <ファイル名> <ファイル名> |
| 全てのファイルの変更を取り消す | git reset –hard @ |
ステージ後の変更を取り消す(git addやコミット前の変更を取り消す)
ステージ前に戻す(ファイル内の変更内容は残す)
| 内容 | 処理 |
|---|---|
| 特定のファイルの変更を取り消す | git reset @ <ファイル名> |
| 複数のファイルの変更を取り消す | git reset @ <ファイル名> <ファイル名> |
| 全てのファイルの変更を取り消す | git reset @ |
ファイルを指定してステージ後の変更を取り消すには、git restore --rm <ファイルパス> も使えます。(git reset を覚えておけば基本的に問題ありません)
ファイルの変更を消す
ステージ前の状態よりも更に遡って、ファイルの変更内容も削除する方法です。(git statusで何も表示されない状態にする)
| 内容 | 処理 |
|---|---|
| 特定のファイルの変更を取り消す | git reset –hard @ <ファイル名> |
| 複数のファイルの変更を取り消す | git reset –hard @ <ファイル名> <ファイル名> |
| 全てのファイルの変更を取り消す | git reset –hard @ |
git reset に --hard オプションをつけるとファイルの変更内容も削除する処理になります。
コミット後の変更を取り消す
コミットメッセージを変更する
| 内容 | 処理 |
|---|---|
| 1つ前のコミット(エディタを開いて編集する) | git commit –amend |
| 1つ前のコミット(コマンドライン上で変更する) | git commit –amend -m “変更後のメッセージ” |
| コミットを指定して変更する(nに遡る数値を入れる) | git rebase -i @~n ・エディタが起動する。 ・対象のコミットのpick を rewordに変更する。 (並びは古い順。新しいコミットが一番下) ・保存して終了(:wq)。 ・エディタが起動する。 ・コミットメッセージを変更する。 ・保存して終了(:wq)。 |
| コミットを指定して変更する(nに遡る数値を入れる。editの場合) | git rebase -i @~n ・エディタが起動する。 ・対象のコミットのpick を editに変更する。 (並びは古い順。新しいコミットが一番下) ・保存して終了(:wq)。 git commit –amend -m “変更後のコミットメッセージ” git rebase –continue |
コミットを取り消す
一つ前のコミットに戻す方法です。
| 内容 | 処理 |
|---|---|
| 変更内容を残す(not stagedの状態になる) | git reset @^ |
| 変更内容も戻す(ファイルの内容も一つ前のコミットの状態になる) | git reset –hard @^ |
指定したコミットの状態に戻す
遡りたいコミットを指定する方法です。
| 内容 | 処理 |
|---|---|
| 変更内容を残す(not stagedの状態になる) | git reset <コミット番号> |
| 変更内容も戻す(ファイルの内容も一つ前のコミットの状態になる) | git reset –hard <コミット番号> |
コミット番号以外にも、@^^^ (3つ前のコミット)や、@~5 (5つ前のコミット)といった指定もできます。
@ は最新のコミットを表します。HEAD と同じです。
コミットを遡る方法
最新のコミットを@として、一つ前のコミットを指定するには^を。2つ前を指定するには^^を使います。
^の数だけ、コミットを遡ります。
| 記号 | 意味 |
|---|---|
| @ | 現在のコミット |
| @^ | 1つ前のコミット |
| @^^ | 2つ前のコミット |
| @^^^ | 3つ前のコミット |
コミットをたくさん遡る場合
3個ぐらいまでならわかりやすいですが、5個遡るとなると、@^^^^^ となって、正しいコミットを指しているのかわかりにくくなります。
その時は、 @~n を使うとわかりやすくなります。 n に遡りたい数値を入れます。例えば、@~3 なら3つ前のコミットになります。
| 記号 | 意味 |
|---|---|
| @ | 現在のコミット |
| @~1 | 1つ前のコミット(@^ と同じ) |
| @~3 | 3つ前のコミット (@^^^ と同じ) |
| @~7 | 7つ前のコミット |


