git reset —hardしてしまった時に元に戻す方法
「タタターン、タッーン! ($ git reset —-hard)」
「半日分の作業がぁぁぁぁ….😇」
今まさに、こんな状況じゃないでしょうか?
そんな絶望のどん底にいるあなたを救済したい!
本記事ではgit reset —hard
を元に戻す方法をご紹介します!
2つのあるので、状況にあった方をご参照ください。
- 過去のコミットにリセットしてしまった場合
- コミットせずにリセットしてしまった場合
過去のコミットにリセットしてしまった場合
1つ目は、過去のコミットにリセットしてしまった場合です。
こちらは比較的簡単に復旧できます。
例
以下のように、1.txt
と2.txt
を作成し、それぞれコミットした状態を考えます。
# Commit: Add 1.txt
$ echo 1 >> 1.txt
$ git add -A
$ git commit -m "Add 1.txt"
# Commit: Add 2.txt
$ echo 2 >> 2.txt
$ git add -A
$ git commit -m Add 2.txt
$ git log --oneline
0ae8a0a (HEAD -> main) Add 2.txt
6776aad Add 1.txt
ここで、手が滑って1つ目のコミットにリセットしてしまい、2.txt
を消してしまいました😇
git reset --hard 6776aad
HEAD is now at 6776aad Add 1.txt
解決法
これを解決するには、git-reflogを使います。
reflogはHEADの動き、つまり自身のgitの操作履歴を参照できるコマンドです。
実行してみると、先ほど実行したreset —-hard
が直近のreflogとして出力されます。
さらに、それ以前のコミットも出力されているのがわかります。
$ git reflog
# ↓手が滑ってやってしまった reset --hard
6776aad (HEAD -> main) HEAD@{0}: reset: moving to 6776aad
# Commit: Add 2.txt
0ae8a0a HEAD@{1}: commit: Add 2.txt
# Commit: Add 1.txt
6776aad (HEAD -> main) HEAD@{2}: commit (initial): Add 1.txt
今回は、2.txtを追加したCommit: Add 2.txt
に戻したいので、HEAD@{1}
を指定してreset —hard
をかけることで、元に戻すことができます。
git reset --hard HEAD@{1}
見事、元に戻りました! やったね🎉
git log --oneline
0ae8a0a (HEAD -> main) Add 2.txt
6776aad Add 1.txt
コミットせずにリセットしてしまった場合
続いて、ステージに追加したファイルを、コミットせずにリセットしてしまった場合です。
こちらは、コミットした場合に比べて、少し厄介です。
例
以下のように
①1.txt
を作成
② 1.txt
を編集、2.txt
を作成
した状態を考えます。
# ① Add 1.txt
$ echo 1 >> 1.txt
$ git add -A
$ git commit -m "Add 1.txt"
# ② 1.txtを編集、2.txtを作成
$ echo 1 >> 1.txt
$ echo 2 >> 2.txt
$ git add -A
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: 1.txt
new file: 2.txt
ここで何を血迷ったのかgit reset —hard
を実行してしまいました😇
$ git reset --hard
HEAD is now at de7c406 Add 1.txt
解決法
今回はステージに追加しただけで、一度もコミットしていないので、reflogが使えません。
そこで登場するのが、git fsck コマンドです。
fsckはLINUXのfsck(file system check)から来ているとおもわれ、gitにおいてもデータの検査と修復を行います。
まず最初に、git fsck --lost-found
で、先ほどコミットされなかったファイルのblobを書き出します。
git fsck --lost-found
Checking object directories: 100% (256/256), done.
dangling blob 0cfbf08886fca9a91cb753ec8734c84fcbe52c9f
dangling blob 6ed281c757a969ffe22f3dcfa5830c532479c726
これで、先ほど消してしまったファイルのblobが、.git/lost-found/other
ディレクトリに出力されます。
ls ./.git/lost-found/other
0cfbf08886fca9a91cb753ec8734c84fcbe52c9f # 2.txtのblob
6ed281c757a969ffe22f3dcfa5830c532479c726 # 1.txtのblob
ファイルの中身を見るには、git show {id} で見ることができます。
git show 0cfbf08886fca9a91cb753ec8734c84fcbe52c9f
2
あとは中身を見ながら1つずつファイルを戻していきます。
# 1.txtの編集を戻す
git show 6ed281c757a969ffe22f3dcfa5830c532479c726 > 1.txt
# 2.txtを追加を戻す
git show 0cfbf08886fca9a91cb753ec8734c84fcbe52c9f > 2.txt
復旧できました!やったね🥰
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: 1.txt
new file: 2.txt
以上、特にコミットしている場合はかんたんに戻せるので、もう一回同じことをする前に、一度試してみることをお勧めします!!
Discussion
まさにこちらでした。。本当にありがとうございます。。!助かりました、、!
救済できて嬉しいです🦑