← 上一章:【狀況題】啊!不小心把檔案或目錄刪掉了… 下一章:【狀況題】不小心使用 hard 模式 Reset 了某個 Commit,救得回來嗎? →
【狀況題】剛才的 Commit 後悔了,想要拆掉重做…
這個狀況很常見,雖然使用的指令 git reset
看起來很簡單,但因不少人誤解 Reset 指令的意思,所以反而是很多學習 Git 的人容易卡關的地方。
退一步海闊天空
先看一下我們目前的 Git 紀錄:
$ git log --oneline
e12d8ef (HEAD -> master) add database.yml in config folder
85e7e30 add hello
657fce7 add container
abb4f43 update index page
cef6e40 create index page
cc797cd init commit
如果想拆掉最後一次的 Commit,可以使用「相對」或「絕對」的做法。「相對」的做法可以這樣:
$ git reset e12d8ef^
在最後面的那個 ^
符號,每一個 ^
符號表示「前一次」的意思,所以 e12d8ef^
是指在 e12d8ef
這個 Commit 的「前一次」,如果是 e12d8ef^^
則是往前兩次,以此類推。不過如果要倒退五次,通常不會寫 e12d8ef^^^^^
,而會寫成 e12d8ef~5
。
而且因為剛好 HEAD
跟 master
目前都是指向 e12d8ef
這個 Commit,而且 e12d8ef
這個數字也不好記,所以上面這行,通常也會改寫成:
$ git reset master^
或
$ git reset HEAD^
以這個例子來說會得到一樣的結果。(分支以及什麼是 HEAD 將於後面的章節再做說明)
以上是「相對」的方式。如果你很清楚想要把目前的狀態退回到哪個 Commit,可以直接指明:
$ git reset 85e7e30
它就會切換到 85e7e30
這個 Commit 的狀態,因為 85e7e30
剛好就是 e12d8ef
的前一次 Commit,以這個例子來說也會達到跟「拆掉最後一次的 Commit」一樣的效果。
如何在 SourceTree ,Commit 後悔了,想要拆掉重做
如果使用 SourceTree,可以選擇你想要 reset 到的 Commit,例如想要一口氣退 3 個 Commit,就在想要去的 Commit 上按滑鼠右鍵,選擇「Reset master to this commit」:
接著會有個對話框要你選模式,這裡先選預設的「Mixed」:
按下 OK 鈕之後就一口氣退掉 3 個 Commit 了。
是說,Commit 拆掉了,那拆出來的那些檔案跑哪去了?這問題的答案跟接下來要介紹的 Reset 模式有關。
Reset 的模式
git reset
指令可以搭配參數使用,常見到的三種參數,分別是 --mixed
、--soft
以及 --hard
,不同的參數執行之後會有稍微不太一樣的結果。
mixed 模式
--mixed
是預設的參數,如果沒有特別加參數,git reset
指令將會使用 --mixed
模式。這個模式會把暫存區的檔案丟掉,但不會動到工作目錄的檔案,也就是說 Commit 拆出來的檔案會留在工作目錄,但不會留在暫存區。
soft 模式
這個模式下的 reset,工作目錄跟暫存區的檔案都不會被丟掉,所以看起來就只有 HEAD 的移動而已。也因此,Commit 拆出來的檔案會直接放在暫存區。
hard 模式
在這個模式下,不管是工作目錄以及暫存區的檔案都會丟掉。
畫個表格整理一下:
模式 | mixed 模式 | soft 模式 | hard 模式 |
---|---|---|---|
工作目錄 | 不變 | 不變 | 丟掉 |
暫存區 | 丟掉 | 不變 | 丟掉 |
如果上面的說明對你來說不容易想像到底發生什麼事,用白話一點的方式說明,你只要記這些不同的模式,將會決定「Commit 拆出來的那些檔案何去何從」,讓我再用另一個表格來解釋:
模式 | mixed 模式(預設) | soft 模式 | hard 模式 |
---|---|---|---|
Commit 拆出來的檔案 | 丟回工作目錄 | 丟回暫存區 | 直接丟掉 |
但是 Commit 拆掉之後又後悔了,可以再撿回來嗎?
當然可以,甚至是使用 --hard
模式拆掉的也都能撿回來,我們在下一個章節「【狀況題】不小心使用 hard 模式 Reset 了某個 Commit,救得回來嗎?」就會介紹如何撿回來。
【觀念】不要被 Reset 這個字給誤導了!
Reset 這個英文單字的翻譯是「重新設定」,但事實上 Git 的 Reset 指令用中文來說比較像是「前往」或「變成」,也就是「go to」或「become」的概念。當執行這個指令的時候:
$ git reset HEAD~2
這個指令你原本可能會解讀成「請幫我拆掉最後兩次的 Commit」,但其實用「拆」這個動詞只是我們比較容易理解而已,事實上並沒有真的把這個 Commit「拆掉」(放心,所有的 Commit 都還在)。
正確的說,上面這個指令應該要解讀成「我要前往兩個 Commit 之前的狀態」或是「我要變成兩個 Commit 之前的狀態」,而隨著使用不同的參數模式,原本的這些檔案就會丟去不同的區域。
因為實際上 git reset
指令也並不是真的刪除或是重新設定 Commit,只是「前往」到指定的 Commit,那些看起來好像不見的東西只是暫時看不到,但隨時都可以再撿回來。
Reset 是 Git 裡很常用的指令,所以一定要建立正確的觀念,操作 Git 才能真的達到隨心所欲的境界喔。
← 上一章:【狀況題】啊!不小心把檔案或目錄刪掉了… 下一章:【狀況題】不小心使用 hard 模式 Reset 了某個 Commit,救得回來嗎? →
Comments