Edited at

git reset 解説

More than 1 year has passed since last update.

git reset コマンドは、初心者が一番訳が分からないところでしょうか。

このコマンドで色んなことが出来るので、どういう場合にどう使えばいいのか混乱してしまいます。

でも実は、非常にシンプルな動作をしているのです。


git の仕組み

git resetを理解する為に、まずgitの仕組みを抑えておきます。

developブランチをチェックアウトした状態で、Bのコミット直後を表しています。

項目
説明

develop
checkout中のブランチ

A, B
コミットデータ

INDEX
git add で登録される領域。この内容がコミットとして登録されます。

ワーキングツリー
編集対象のローカルのファイルやディレクトリ

developからワーキングツリーまで縦に並んでいるのは、これらが一致しているということを表しています。

参考:ブランチの真実

ブランチは日本語で「枝」になりますが、gitのブランチはコミットを1つしか持ちません。

ブランチは、どのコミットから始まったかという情報を持っておらず、

あくまでも1コミットに付けられた「別名」に過ぎないのです。


ワーキングツリーを編集

developブランチをcheckoutして、ファイルを編集した状態です。

ワーキングツリーのみ先に進んでいます。


git add で登録

ワーキングツリーの内容を git add で全て登録した状態です。

INDEXも進みました。


git commit

INDEXに登録されている内容をコミットした状態です。

INDEXは、コミットした後も同じ内容で保持されます。


git reset の動き

git reset コマンドは、checkout中のブランチを指定コミットに紐づけ直すという動作をします。


直前のコミットを取り消したい場合

Cをコミットした状態から以下コマンドを実行します。

$ git reset HEAD^

HEADは、checkout中のブランチに紐づいており、つまりはコミットの「別名」にもなります。

^ は、その1つ前のコミットを表すので、HEAD^はBコミットを表します。

コマンド実行後

HEADとHEADが紐づくブランチ(develop)がBコミットに移動します。

INDEXにもBコミットの内容が反映されます。

ワーキングツリーは変化しません。

これによって、Cのコミット直前に戻ることになります。


ブランチのコミットを全て取り消したい場合

例えば、masterブランチからdevelopブランチを作成してコミット作業を進めていたけど、それらを全て取り消したい、という場合。

$ git reset --hard master

とします。

master = Aコミットの場合です。

これも同様に、developブランチがmasterブランチと同じコミットに紐づけられる動作です。

INDEXもAコミットの内容が反映されます。

そして、--hard オプションにより、ワーキングツリーにも反映されます。


git add を取り消す場合

git add で登録したこの状態から、

$ git reset

とすると。

となります。

これは、

$ git reset

こう書いたのと同じです。

$ git reset HEAD

Bコミットに紐づいている状態から、同じBコミットに紐づけ直すだけなのですが、

その際にINDEXがBコミットの内容で再生成されることで、結果として、git addで登録していた内容がキャンセルされる、

ということになります。