git reset
は、HEAD
を戻すコマンド。だが、インデックスの削除など HEAD
を戻す以外の使い方もあり、混乱したのでまとめておく。
$ git reset <オプション> <コミット>
コミットは、コミットのハッシュのほか、HEAD
やブランチ名などで指定する。指定しなかった場合は HEAD
となる。
git reset のオプション
オプション | 動作 |
---|---|
--soft | HEAD だけ戻す |
[--mixed] | HEAD とインデックスを戻す |
--hard | HEAD とインデックスとワークツリーを戻す |
(--mixed は省略可)
git reset でコミットを指定しない(=HEAD
を指定する)とき
HEAD
は、通常、最新コミットを指す。
コマンド | 動作 |
---|---|
git --soft HEAD | 何も変わらない |
git [--mixed] HEAD | インデックスを戻す |
git --hard HEAD | インデックスとワークツリーを戻す |
例1
A
というファイルを作って、git add A
して、コミット。B
というファイルを作って、git add B
して、コミット。C
というファイルを作って、git add C
した。
という状況。
git reset
git reset HEAD
は、インデックスを HEAD
の内容に戻す。
add
したことをキャンセル(unstage)するのに、git reset HEAD
が使われる。
ただ、このコマンドは git restore --staged
に変わりつつあることも知っておきたい。(関連記事)
git reset --hard
git reset --hard HEAD
は、ワークツリーとインデックスを HEAD
の内容に戻す。つまり、最新コミット直後のような状態になる。
例2
A
というファイルを作って、git add A
して、コミット。B
というファイルを作って、git add B
して、コミット。C
というファイルを作った。
インデックスにはまだ追加していないという状況。
git reset
git reset HEAD
は、インデックスを HEAD
の内容に戻すので、この例では何も変わらない。
git reset --hard
git reset --hard HEAD
は、ワークツリーとインデックスを HEAD
の内容に戻す。
(git status
のメッセージによると、ステージしていない変更を破棄するには checkout
(または restore
)を使う)
Untracked files に注意
ここが初心者(自分)にとっては罠だった。
git reset --hard (HEAD)
すると、インデックスとワークツリーが最新コミットの状態に戻る。と書いてあったりする。
ただし、Untracked files(まだ一度も git に add されていないファイル)は影響を受けない。つまり、最新コミットの後新たに作ったファイルは消えず、Untracked files として残ったままになる。
Git を使っている人たちには当然すぎることなので言及されていないのだろうが、最初そこがわかっておらず、git reset --hard
したのにワークツリーが戻ってない!やっぱり git わからん…となった。
Untracked files は、reset
してもブランチを切り替えても影響を受けないということを覚えた。