基本指令外加一些輔助操作,到目前為止應該算是介紹完畢。
在開始進入下一個主題之前的 幾篇 文章,我打算來聊聊一些能承上啟下的觀念。
對...大概會有一兩篇都是閒聊性質
這些觀念跟指令沒什麼關係,但是如果沒把他搞懂的話,卻會 直接影響 部分指令的操作。
由於筆者不太喜歡在主要內容中穿插各種補充讓文章失焦 雖然已經...,於是乾脆把一些觀念與問題獨立出來聊。
希望大家能因為這幾篇文章更認識 Git ,同時可以在開始介紹其他操作之前,奠定一些概念。
我們再次把這個線圖請出來,並且把關注點放在最右邊的 CommitID 。
這些字母「看起來」很沒意義,不過它卻是我們在用 Git 版控時,十分重要的資訊之一。
這個 ID 其實有一個名字,叫做「哈希值 (hash 值)」(雖然我每次都會念成嘻哈值)。
他是透過密碼學的雜湊函數「哈希函數」所計算出來的值,英文名稱是 SHA-1
(Secure Hash Algorithm 1)。
所以如果讀者在系列文章中,看到 「commitID」、「哈希值」、「SHA」、「SHA-1」,都是在表示這個看起來像亂碼的值。
探討這個值怎麼產出的不是這邊的重點,我們只要知道 Git 在執行 git commit
指令時,會自動針對 Commit 產好哈希值就好。
記得我們把每個 Commit 版本比喻成一筆一筆的「訂單」,那麼這個「哈希值」就可以把他當成「訂單編號」了。
每個 Commit 都會有這個 唯一 (註1) 的哈希值,好讓我們可以透過它去找到 Commit。
不知道讀者們網購時有沒有使用「訂單編號」的經驗?
例如商品遲遲不出貨,想去問找客服查狀態時,我們就會拎著這個「訂單編號」,問客服這筆訂單是怎麼一回事?
在 Git 的世界也是一樣,當我們想去「操作」某一筆 Commit,就必須要有個依據,讓 Git 知道「那麼多 commit ,是要處理哪一個?」
而這個「哈希值」就是其中一個 (註2) 能讓 Git 認得 commit 的依據。
註 1. SHA-1 值是有重複的可能性,不過要重複的機率極低,我們幾乎可以當作他就是唯一值。
註 2. 除了 Commit 的 SHA-1 之外,我們也能用 「分支名稱」 ,或是 「
HEAD
」 來找到想取得的 Commit,文末會介紹「相對位置」的找法。
讀者應該有看過完整的 commitID 的長度,總長大概有 40 個字母之多,如果真的要拿它操作,不太可能慢慢輸入到終端機之中。
Git 因此讓我們輸入前幾個字母即可,只要輸入的值沒跟其他 commitID 開頭重複, Git 就能找到相對應的 Commit。
我們在執行 git log --oneline
指令時,就是只呈現 7 碼 commitID 來給我們使用:
$ git log --oneline -5
c159182 (HEAD -> dev) Merge branch '拉姆' into dev
8ec01e1 Merge branch '雷姆' into dev
631d193 Merge branch '愛蜜莉雅' into dev
4e16000 (Rem) 完成雷姆頁面
b41c499 (Emilia) 完成愛蜜莉雅頁
不過,我就懶!我連前面幾個英數字,都懶得慢慢對照 key 到終端機之中,我都直接用複製貼上大法來做這件事。
介紹一下,之後如果要操作 commitID,可以怎麼透過 GUI 複製資料。
或是
Ctrl
+ C
Command
+ C
,反正就是你我都很熟的複製快捷鍵)跟 Fork GUI 動作一模一樣!
唯一要注意的是,記得要在「Commit」按右鍵,如果在「分支圖標」按右鍵,會出現操作分支的選項。
此外,這個介面 不支援 鍵盤快捷鍵 (Ctrl
+ C
),請多加小心。
在執行 git log
指令的時候,會看到這樣的內容: (HEAD -> master):
$ git log --oneline
e5f6e37 (HEAD -> master) Initial commit
這個 master
應該就是「master
分支」的意思,不過怎麼還有一個 HEAD ->
?
帶大家認識一個 Git 的關鍵詞:HEAD
。
HEAD
是一個「指標」(你可以想像成箭頭),會指著我們「目前所在位置」。
這個 HEAD
在 Fork GUI 中,會用「✓
」來表示:
在 Git Graph 則是 「○
」:
或是也可以直接看 VSCode 視窗左下角顯示的資訊,也是在提示我們目前所在位置:
HEAD
一般來說是會指著某個分支,像是上圖的例子, HEAD
都是指著 Emilia
分支。
不過如果所在位置沒有分支,他也會直接指著 Commit,例如這樣:
一般來說,在操作 Git 時,不該 是這種狀態!! 觀念將會在【分支篇】說明。
截至目前的文章,我們還沒有建立任何分支的行為,而且也還沒有討論如何讓分支「回到過去」的 commit。
這樣的操作模式下,HEAD
永遠是指著我們唯一的那條分支 master
,而他們都是對應到 最新一次 的 commit。
雖然【一起學 Git 吧!- 分支篇】 還沒開始連載(?),不過身為作者的我可以先劇透一件事 官方暴雷不可取
當建立新的分支之後,我們是可以讓 HEAD
在不同分支來回移動的,這件事也代表著: HEAD
不會 永遠指在 master
分支上。
也是因為後續 Git 的操作,我們所在位置不一定都是 最新一次 的 commit,所以 Git 才會需要有一個特殊的 HEAD
指標,讓我們能知道自己到底在 「Git 版控樹」的哪個位置上。
前文有示範過怎麼複製特定的 CommitID 回來用,不過未來如果操作的 指令 需要用到 CommitID ,也可以透過用 HEAD
往前推算 commit 的方式,告訴 Git 想要執行哪一個版本。
以這個圖為例子,HEAD
目前是指著 dev
分支:
如果要用 HEAD
對應到先前提交的 Commit 有幾種方式:
使用 「^
」:代表 「上一個」的意思。
目前 HEAD 指著 dev
分支,也就是 d75c2655
。
HEAD^
表示 2dbd1a34
。HEAD^^
表示 e4c92f3b
。HEAD^^^
表示 7f50fc5a
。使用「~n
」:代表往前 n 筆 commit。
HEAD~1
表示 2dbd1a34
。HEAD~2
表示 e4c92f3b
。HEAD~3
表示 7f50fc5a
。雖然看起來好像很複雜,不過筆者最常使用的相對位置,最多也就到 HEAD^^
,如果要抓更遠的 commitID ,比起操作相對位置,直接用前文說明的操作方式把 commitID 複製出來用可能還比較快呢!
補充:這個操作在 Git GUI 中 用不到,因為這是用「相對位置」的方式告訴 Git 要操作之前的 commit 的語法。
而如果都已經使用 GUI 了,就不要把自己搞得這麼累,還要用「目前位置」往前推算 commit....,直接用滑鼠點擊特定版本操作想執行的動作就可以了!
這篇文章稍微介紹一下 commitID 與 HEAD
的觀念,以及取得 commit 的方式。
其中最重要的概念會是,如果有指令需要輸入 CommitID ,也可以使用 「HEAD
關鍵字操作相對位置」來告訴 Git 想操作的版本。
雖然 GUI 派的使用者可能不太需要知道怎麼操作 HEAD
或複製出 commitID。
不過對兩者有一定程度的認識之後,未來若有相關的動作,能更清楚自己的操作 GUI 的過程,Git 實際是在做什麼事情。
若是指令派的使用者,無論是觀念或是資料的取用,在之後的操作一定會用到,也請多加留意!
個人覺得 學git,或是說要學好git一定要會用終端,看到很多人用GUI操作的人,很多觀念都不清楚,或是有很多 rollback / rebase / revert / cherry-pick 等功能都不知道,還是開2個資料夾在那邊複製貼上 (?
最近寫鐵人賽也有體悟到,指令的觀念寫完之後,GUI 只是去找對應的操作而已 XD
有辦法從指令開始學習的話,我也頗推薦直接學指令來操作 Git。