git add . 後沒有 git commit 就 git reset --hard, 有辦法救回消失的檔案嗎?

Ninn Wang
5 min readMar 17, 2020

--

Photo by Markos Mant on Unsplash

標題都這樣下了,肯定是有救回來的。

情境:我寫的專案剛好告了一個段落,下了 git add . 的指令後發現我忘了先新增 .gitignore ,所以多了很多奇奇怪怪的檔案,一時手賤下了 git reset --hard 的指令,在按下 enter 的瞬間已經知道自己做了傻事,但是手速跟不上腦子思考的速度,所以專案就這樣被清空了。

重點:不管做的功能有多渺小,只要 code 已經寫完整了就 commit ,沒有寫完整想 commit 就 commit 也沒關係,反正之後也可以用 rebase 再重新整理所有的 commit ,所以說 commit 真的很重要。

我當初跟周遭的朋友們說我的專案消失的時候大家都跟我說沒救了,重做吧。但我就是很不想重做啊,我就是很懶散不想再做一次一樣的事情,所以就花了一個晚上的時間查這些東西,還好被我找到了ㄏ。

Git 是一個很強大的工具,比我們想的都還要強。在下了 git add . 的指令後雖然還沒有 commit ,但這些被 add 的檔案已經被存在文件裡了,就算被丟進垃圾桶裡也救得回來。

實驗:我建立了一個資料夾“Folder”,新增三個檔案:file1, file2, file3,然後下指令 git add . ,接者馬上 git reset --hard,所有檔案就消失了。

因為我當初是整個專案消失,所以我的做法是先把所有的 hashes 存到一個檔案,用以下這個指令。這個指令會還原電腦裡所有沒有被 commit 過的檔案,可能包含一些在前公司時期開發的功能,或是自己寫的 side project ,甚至是被你刪除的檔案,全部都會出現在這裡,這就是沒有 commit 就 reset 的代價,所以在檔案還原後要自己將需要的檔案另外篩選出來。

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > allhashes

接著“Folder”裡會出現一個叫做“allhashes”的檔案,點開裡面會放著被我們 reset 掉的 hash 們。

這裡需要對 allhashes 做一些編輯,把這三個 hash 包成一個 array ,跑 for 迴圈,最後要把副檔名用 .py 結尾。

因為我們要用 python 的語法將這些 hash 分別還原成三份檔案(幫大家長姿勢: python 語法是 Mac 內建的喔!)!在 command line 打下:

python3 allhashes.py

剛剛消失的檔案都回來了!

網路上也有其他針對 xcode 開發環境的救法,提供給大家參考。這個方法我也試過,但我沒有辦法從垃圾桶裡找回所有的檔案,所以用前面介紹的方法是最完整也最保險的。

--

--