git resetが覚えられない
git reset が覚えられません。
コミットを取り消せるというけれど引数は取り消すコミット?
最新コミットを取り消すには HEAD ? それとも HEAD~1 ?
man 説明
git reset のドキュメントを見てみます。
Git - git-reset Documentation
git reset [<mode>] <commit>changes which commit HEAD points to. This makes it possible to undo various Git operations, for example commit, merge, rebase, and pull.
git reset コマンドですることは、「HEAD が指している commit を変更すること」です。
どこに変更するかは引数の <commit> で指定します。
そして、HEAD が変更されたことで、「例えば commit, merge, rebase, and pull といった Git 操作を取り消し」できます。
○○を取り消すという風に覚えるのではなくて、HEAD が指している commit を変更する、と覚えておくと応用が効いていいです。
例えば、git reset HEAD~1 とすると HEAD は最新のひとつ前の commit を指すようになります。
元々の最新の commit は参照されなくなり削除されるので、結果として取り消したことになります。
冒頭の「最新コミットを取り消すには HEAD ? それとも HEAD~1 ?」の疑問では、HEAD~1 とするのが正解でした。
オプションも理解する
HEAD が指している commit を変更したときにインデックスやワーキングツリーの状態はどうなるのでしょう?
コミットを取り消すという目的でコマンドを実行する場合、だいたいはインデックスも変更されたコミットに追従しておいてほしいです。
そうでないと、これから修正したいファイルが既にインデックスされている状態になっていることになるので。
git reset コマンドのデフォルトの動作では、HEAD が指している commit を変更して、インデックスも追従して変更されます。
ファイルはインデックスされていない状態になります。
デフォルトの動作が一般的な取り消しのユースケースに合うようになっているんですね。
明示的にオプションを指定するなら git reset --mixed <commit> です。
あえてインデックスはそのままにするのは、--soft オプション。
インデックスに加えてワーキングツリーの変更も取り消してしまうのが、--hard オプション。(これは取り返しがつきません。)
git reset --soft HEAD~5; git commit とすると最新の 5 つのコミットを 1 つのコミットにまとめる、という使い方もできるとドキュメントにあります。
まとめ
git reset の動作の理解があいまいだったのでドキュメントを見てみました。
「HEAD が指している commit を変更すること」というのが reset の動作でした。