git resetをちゃんと理解する
はじめに
過去を振り返ってみて、gitの理解が一段階深まったなと感じたのはgitの HEAD の概念を理解したときだった。そしてそのHEADと密接に関連しているのが git reset コマンドだと思う。
なのでgit resetコマンドをちゃんと理解できればHEADの概念の理解も進み、gitの理解も深まるのではないかと考えた。ということで、この記事ではgit resetについてちゃんと理解するための説明を試みたい。
git reset コマンドは何をするのか
git resetは HEADを移動する コマンドである。
HEADとは何か
ではHEADとは何か?
HEADとは、今いるブランチの最新のコミットを指し示すポインタ である。
例えばリポジトリAをgit管理しているとして、リポジトリAで git log
コマンドを実行したときに次のような状態だったとしよう。
$ git log --oneline
193c77e Third commit ★ HEAD
69d2f53 Second commit
1010114 First commit
この場合、最新コミットの 193c77e Third commit
がHEADだ。
git reset [mode] [commit]
git resetコマンドにはいくつかのコマンド体系があるが、最もよく使うのは git reset [mode] [commit]
の形式での実行だろうと思う。
上述の通りgit resetコマンドはHEADを移動するコマンドであった。よってこのコマンドは [commit]の位置までHEADを移動する ということを意味する。
そして[mode]は、HEADを移動するときに「ステージングエリア」と「作業ディレクトリ」を更新するかどうか を指定するオプションとなる。
--
以下、具体例で見てみよう。次の状態のリポジトリがあるとする。
A、B、Cの3つのコミットがあり、何も変更を加えていない状態。HEADは最新のコミットであるCを指している。
git status
コマンドを実行すると次の結果が返ってくる。何も差分が発生していないクリーンな状態だ。
$ git status
On branch master
nothing to commit, working tree clean
git reset --soft HEAD^
modeを--soft
、commitをHEAD^
にしてresetをすると、HEADは1つ前のコミットに移動させるが、ステージングエリアと作業ディレクトリはそのままの状態にする。
※ HEAD^
は最新コミットの1つ前を示す特殊な指定方法(だがよく使う)
git status
コマンドの結果は次の通り。git add
をした状態と考えても良い。
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: file.txt
git reset --mixed HEAD^
modeを--mixed
、commitをHEAD^
にしてresetをすると、HEADとステージングエリアを1つ前のコミットに移動させ、作業ディレクトリはそのままの状態にする。
--mixed
がmodeのデフォルト値である。
git status
コマンドの結果は次の通り。git add
をする前の状態と考えても良い。
$ git status
On branch master
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: file.txt
no changes added to commit (use "git add" and/or "git commit -a")
git reset --hard HEAD^
modeを--hard
、commitをHEAD^
にしてresetをすると、HEAD、ステージングエリア、作業ディレクトリの全てを1つ前のコミットに移動させる。
git status
コマンドの結果は次の通り。差分の発生していないクリーンな状態だが、前のコミットである C
の情報は消え去っている。
$ git status
On branch master
nothing to commit, working tree clean
おまけ:ファイルパスを指定したgit reset
git resetコマンドはファイルパスを指定して実行する形式もある。この場合、指定したファイルをある状態に戻すが、HEAD自体は動かさない という動きになる。
この形式のgit resetを使う典型的なパターンは、「間違えてgit addしてしまったので取り消したい」というケースだろう。以下例。
--
間違えて git add してしまった!
git reset [path]
で 指定したファイルを、HEADの状態に戻す。 すなわち、作業ディレクトリだけ変更が反映された「git add する前の状態」に戻ることになる。