開発ブログ

WWWクリエイターズが送る、Git、CSS、HTML、コマンドライン、Macの便利機能など、開発に関する役立ち情報発信します。気まぐれに更新。

git add の取り消し方法、徹底まとめ。

最終更新:2017-08-03 by Joe

git add してしまったファイルを取り消しするgit コマンドです。

整然と意図をもってコミット履歴を育てて行くには、git add をうまく使いこなして、インデックスの作り方を覚えておくことはすごく重要です。

git add を取り消す方法

add したファイルの更新を、すべて一括で取り消す

git add したファイルの変更内容を、一括でインデックスから削除するには、git reset コマンドを利用します。

git reset の引数に「HEAD」と指定すれば、作業ツリーの状態はそのままで、インデックスへaddした変更が、元の状態に戻ります。なお、引数なしでデフォルトでHEADを指定した事になります。

一旦インデックスを元に戻したら、その後、必要なファイルをaddし直せばまたコミットできます。

git addと、git reset の関係

git addを取り消すgit reset

ちなみに、インデックスから変更を取り除くことを「unstage(アンステージ)」と呼びます。インデックスに入れることを「stage(ステージ)」と呼びますが、その逆の操作を行うことを意味します。

ファイルを指定して add を取り消す

特定のファイルについて、変更内容をインデックスから削除します。こちらも作業ツリーはそのままです。

<path>と書いたのは、フォルダを指定することで、フォルダ配下のすべてのファイルを指定できるからです。これは git add のときも一緒ですね。

これらの操作は、実際「git addの取り消し」と呼ぶよりは、「インデックスを、HEADのコミット状態にリセットする」と言った方が誤解が少なく、イメージもしやすいかもしれません。(使っているコマンドが git reset なので、当たり前といえば当たり前です。)

[補足] git resetは「git addの取り消し」ではない

1点注意が必要なのが、例えば「最後のcommitから2回以上のaddした。」という場合、1回目の変更含めて、すべてリセットされてしまいます。ですので、本当の意味での、「git addコマンドの実行1回分の取り消し」はgitでは不可能です。

addしただけの変更も含め、git では一般的に、commit や stash していない変更内容は、一度失われると取り返せません。

[補足] git add したファイルとHEADの差分を確認

git addしたり、git resetしたりしていると「いまインデックスがどんな状態か」わかりにくくなりそうですが、下記がインデックスとHEADの差分を見るコマンドです。

「--cached」のオプションにより、普段は作業ツリーを対象としているdiffの振る舞いを、インデックスへ変更することができるのでした。

git diffの振る舞いについては、別記事に詳しくまとめたので、ぜひご覧下さい。

「git reset」の振る舞いについて

それでは、良い機会なので、もう少しこの「git reset」コマンドについて、詳しく見ていきます。

git reset は何するのか?

git reset は「現在のブランチの先頭(とブランチ履歴)」や「インデックス」を、指定されたコミットに強制的に書き換えます。

HEADは通常、現在のブランチの先頭コミットを参照していますので、「git reset HEAD」と指定し、HEADの指しているコミット状態へリセットに施す事により、インデックスの状態がそのコミットのと同じ状態になる、すなわち「インデックスを更新する前に戻る」というわけです。

git addを取り消すgit reset

実際は「git reset」とコミット指定を省略すると、デフォルトでHEADとなります。

HEAD以外のコミットにresetする場面

git resetは、引数で「HEAD」以外でもいかなるコミットをも指定できます。

ただ、実勢に特定のコミットの指定を行うようなケースは、合わせて、git reset の代表的な3種類のモードを使い分ける事が多いです。

git resetのモード

冒頭の「取り消し」の操作で使ったのは、引数なし(mixedモード)でした。その他「soft」「hard」というモードが存在し、用途によって使い分けます。

モード指定 動作
git reset --soft 現在のbranchの先頭だけをリセット。(インデックスはそのまま)
git reset
(git reset --mixed)
現在のbranchの先頭と、インデックスをリセット
git reset --hard 現在のbranchの先頭、インデックスも作業ツリーも全部リセット

下図は、HEAD^(HEADの一個前のコミット)の例ですが、このようにリセットされる範囲が異なります。

git reset のオプション

git reset --soft はいつ使うの?

このオプションは、例えば「最新のコミットの内容をちょっとだけ修正したい時」に使います。

「git reset --soft HEAD^ 」と実行すると、 インデックスと作業ツリーはそのままで、HEADの参照が一つ前に戻ります。

もし「デバッグコード削除し忘れ」の修正であれば、あとはその不要なコードを削除してgit commit を実行するだけで直前のコミットを修正できます。これは「git commit . --amend」の動きによく似ています。

git reset soft

git reset はいつ使うの?

上述の例のように、git addを取り消してやり直す時など、コミットを作っている最中に使うでしょう。

git rest --hard はいつ使うの?

このコマンドは、すこし特定の使い方をします。

例えば、「ローカルブランチをリモートブランチで強制上書きする」などする時に、一撃必殺技的に使うことが多いです。ローカルブランチの歴史もろとも、不要なものを全部消し去って、特定の基準点に一気に帰りたい時、というケースだと思います。

とにかく、インデックス、作業ツリーの状態を無視して(変更があろうがなかろうが吹き飛ばして)指定されたコミットと全く同じ状態を作り出します。

git resetについて、より詳しくは、こちらをご覧下さい:

参考リンク

git add も、git resetもだいたいマニュアルには書いてありますね。読みにくいのが難。

git commit の取り消しに関しては、こちらを御覧ください

以上、git add の取り消しについてでした。

それでは、楽しいgit ライフを。