git reset を元に戻すための git reflog コマンド
ファイルの変更はそのままにコミットを戻す $ git reset HEAD^
(--soft
) や、ファイルの変更ごとコミットをなくす $ git reset --hard HEAD^
を叩いた後に、それをまた戻す方法があった。git reflog
というコマンドを使うと、--hard
を使って完全に取り消したコミットでも元に戻せるので紹介。
まずはサンプルとなる環境の紹介。
$ git log # フォーマットして1行にしている
9adb18a 2018-05-17 Second (HEAD -> master)
08d59b1 2018-05-17 First
このような状態だとする。
まずは $ git reset --soft HEAD^
を試してみよう。
$ git reset --soft HEAD^
$ git log
08d59b1 2018-05-17 First (HEAD -> master)
Second
のコミットに含まれていた内容はそのまま保持されるので、git status
を見るとそのファイルが modified:
状態で残っている。
さて、これを Second
のコミットが存在していた状態に戻してみよう。git reflog
の出番だ。
$ git reflog
08d59b1 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
9adb18a HEAD@{1}: commit: Second
08d59b1 (HEAD -> master) HEAD@{2}: commit (initial): First
$ git reflog
を叩くと、このように過去のコミット履歴を眺められる。今回は Second
のコミット時点に戻りたいので、2行目の HEAD@{1}
という指定を覚えておく。
確認したら、以下のように git reset
を叩く。
$ git reset --soft HEAD@{1}
$ git log
9adb18a 2018-05-17 Second (HEAD -> master)
08d59b1 2018-05-17 First
コレで戻すと、Second
のコミット ID も元通りに戻せる。
勿論、--hard
で戻してしまった時も同様に戻せる。
# 「--hard」オプションで戻す
$ git reset --hard HEAD^
HEAD is now at 08d59b1 First
$ git log
08d59b1 2018-05-17 First (HEAD -> master)
# Second が跡形もなく消えている。ファイルの変更も破棄された
$ git reflog
08d59b1 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
9adb18a HEAD@{1}: reset: moving to HEAD@{1} # ← ココに戻す
08d59b1 (HEAD -> master) HEAD@{2}: reset: moving to HEAD^
9adb18a HEAD@{3}: commit: Second
08d59b1 (HEAD -> master) HEAD@{4}: commit (initial): First
# コレで戻る
$ git reset --hard HEAD@{1}
HEAD is now at 9adb18a Second
$ git log
9adb18a 2018-05-17 Second (HEAD -> master) # ← コミット ID も元通り
08d59b1 2018-05-17 First
これは便利。もう git reset
事故に怯えなくて済むぞ…!