項目 widget-area-1 尚未註冊或是沒有一個 view.php 檔案.
項目 widget-area-1 尚未註冊或是沒有一個 view.php 檔案.
項目 search-input 尚未註冊或是沒有一個 view.php 檔案.

【Git 備份還原 #1】git reset, git checkout | 萬能又危險的 git 復原神器?! 不論怎麼樣的修改都可以還原的版本方式!

前言

這其實也是個 git 的面試經典考題,git reset 與 git checkout 都可以幫我們移動到某一個版本紀錄 (commit)上,
那他們兩個有什麼差別呢?

沒事請用 git checkout,git reset 很好用,但也很危險

版本紀錄本身是有「時間相依的」,因此我們不能夠任意的修改過去與未來的因果關係,

例如:因為下雨,才撐傘,
因為撐傘,傘才被風吹壞。

我們可以得到:下雨 -> 撐傘 -> 傘壞

然後我們不可以把歷史中的過程進行修改,變成「下雨 -> 傘壞」,整個因果都亂了,
git reset 的危險類似這樣的概念,因為「雲端存在這樣的歷史」,而「本地的歷史已經亂了」,導致無法合併 (不能 push) 的狀態

如果有讀過我的其他 git 筆記,我的老師一直都有在強調一個觀念,
沒事不要「亂 push 上雲」,除非你很確定現在的版本順序非常正確
因為「在 Push 之前」,我們可以輕鬆的用 reset 搞定上面的問題,但碰到的「remote 歷史不一致問題」
就會變超級麻煩… 甚至我都有點懶得慢慢的處理這種問題

圖解

為了方便理解,這裡我們把 commit id 替換成時間,更突顯出時間軸的概念

我們可以從下面看出 git reset 與 git checkout 從 11:00 回到 10:00 時的差別

  • commit 當下最新的狀態

我們可以注意我們的 HEAD 與 master 都在最新的狀態

git checkout

主要有兩種用法 commit 與 branch,但都是讓目前的工作目錄回到指定的狀態,
branch 會是 branch 目前的 head,
而我自己最常用的是去指定 commit id。

小技巧:commit id 很長還要慢慢打不好用?其實可以不用打完,打前幾個字就會智慧的自動判斷了。
如果前幾個字有出現重複,他也會提示你,通常再多打幾個字就可以確定那「唯一的 commit id」

git checkout <branch name>
git checkout <commit id>
  • checkout 後,我們暫時移動到過去的版本

這是我們最經常用的操作

留下了 master,我們可以當作一個旗標,
我們之後想回去的時候,只需要 git checkout master 就能隨時回去,
因此這個旗子非常重要,不能隨便亂改,
不然我們可能就回不去了!!

git reset

git reset –soft

簡單來說,就是回到 git add 後、git commit 前的狀態,
也因此,最新的 master 會被移動,我們沒辦法透過 git checkout master 回去!
「事實上,使用 git reset 也沒必要回去了,我們用 git reset 就是要消除最新的 commit」

git reset (–mixed): default

簡單來說,就是回到 git add 前的狀態,
除了不要最新的 commit,連 modified 的狀態也回復了

git reset –hard

個人也非常常用的功能,直接把檔案完全還原成自己想要的「當時狀態」

完全回到某個版本的狀態,連檔案也修改,
然而這個指令也是最危險的,建議在進行此操作的過程中,

完全控制在 local 使用,不要牽扯到 remote

注意到了嗎? 「如果是 reset,11:00 的紀錄會因為時空回溯而消失!!!

你應該會想問,那如果 reset 我還回的去嗎? 可以,但前提是你必須要有他的 commit id,
這可以用 git reflog 查
可是既然都要回去了,為何不當初就用 git checkout 移動就好呢?

checkout, reset 兩者都有必要性

上面我們似乎講了 reset 很不好、很危險,那他的必要性是什麼?
我們偶爾會做錯事情 (不要以為你很聰明,就不會做錯事XDD)

像是不小心把「很大的檔案」加到了 commit 裡面,導致後續同步時變超久
這時候這種「黑歷史」,何必讓他留在時間軸上呢?

git reset 就是專門砍「黑歷史」的工具,而如果在 local 的資料夾使用得宜,
其實會是個非常好用管理版本工具,「砍掉任何不是重要里程碑的 commit、砍黑歷史」,都非常好用!

因此如果我們想要,我們甚至可以做到:

我覺得 10:00 的紀錄沒有價值,或者 11:00 更具有代表性,
也能代表 10:00,因此 10:00 沒必要成為一個版本

就可以透過 reset 改成這樣: