# 前言

基本指令外加一些輔助操作,到目前為止應該算是介紹完畢。

在開始進入下一個主題之前的 幾篇 文章,我打算來聊聊一些能承上啟下的觀念。
對… 大概會有一兩篇都是閒聊性質

這些觀念跟指令沒什麼關係,但是如果沒把他搞懂的話,卻會 直接影響 部分指令的操作。

由於筆者不太喜歡在主要內容中穿插各種補充讓文章失焦 雖然已經…,於是乾脆把一些觀念與問題獨立出來聊。

希望大家能因為這幾篇文章更認識 Git ,同時可以在開始介紹其他操作之前,奠定一些概念。

# 聊聊 CommitID

我們再次把這個線圖請出來,並且把關注點放在最右邊的 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

讀者應該有看過完整的 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 複製資料。

# 使用 Fork GUI 取得 CommitID

  1. 對著那一列 Commit 點右鍵
  2. 點選 Copy Commit SHA

或是

  1. 左鍵選到 Commit
  2. Ctrl + C
    ( Mac 應該是 Command + C ,反正就是你我都很熟的複製快捷鍵)

Alt text

# 在 VSCode Git Graph 套件取得 CommitID

跟 Fork GUI 動作一模一樣!

唯一要注意的是,記得要在「Commit」按右鍵,如果在「分支圖標」按右鍵,會出現操作分支的選項。

此外,這個介面 不支援 鍵盤快捷鍵 ( Ctrl + C ),請多加小心。

Alt text

# 聊聊 HEAD

在執行 git log 指令的時候,會看到這樣的內容: (HEAD -> master)

$ git log --oneline
e5f6e37 (HEAD -> master) Initial commit

這個 master 應該就是「 master 分支」的意思,不過怎麼還有一個 HEAD ->

帶大家認識一個 Git 的關鍵詞: HEAD

HEAD 是一個「指標」(你可以想像成箭頭),會指著我們「目前所在位置」。

這個 HEADFork GUI 中,會用「 」來表示:
Alt text

Git Graph 則是 「 」:
Alt text

或是也可以直接看 VSCode 視窗左下角顯示的資訊,也是在提示我們目前所在位置:
Alt text

HEAD 一般來說是會指著某個分支,像是上圖的例子, HEAD 都是指著 Emilia 分支。

不過如果所在位置沒有分支,他也會直接指著 Commit,例如這樣:

一般來說,在操作 Git 時,不該 是這種狀態!! 觀念將會在【分支篇】說明。

截至目前的文章,我們還沒有建立任何分支的行為,而且也還沒有討論如何讓分支「回到過去」的 commit。

這樣的操作模式下, HEAD 永遠是指著我們唯一的那條分支 master ,而他們都是對應到 最新一次 的 commit。

雖然【一起學 Git 吧!- 分支篇】 還沒開始連載 (?),不過身為作者的我可以先劇透一件事 官方暴雷不可取
當建立新的分支之後,我們是可以讓 HEAD 在不同分支來回移動的,這件事也代表著: HEAD 不會 永遠指在 master 分支上。

也是因為後續 Git 的操作,我們所在位置不一定都是 最新一次 的 commit,所以 Git 才會需要有一個特殊的 HEAD 指標,讓我們能知道自己到底在 「Git 版控樹」的哪個位置上。

# 用 HEAD 尋找相對於目前位置的 commit

前文有示範過怎麼複製特定的 CommitID 回來用,不過未來如果操作的 指令 需要用到 CommitID ,也可以透過用 HEAD 往前推算 commit 的方式,告訴 Git 想要執行哪一個版本。

以這個圖為例子, HEAD 目前是指著 dev 分支:

如果要用 HEAD 對應到先前提交的 Commit 有幾種方式:

  1. 使用 「 ^ 」:代表 「上一個」的意思。
    目前 HEAD 指著 dev 分支,也就是 d75c2655

    • HEAD^ 表示 2dbd1a34
    • HEAD^^ 表示 e4c92f3b
    • HEAD^^^ 表示 7f50fc5a
  2. 使用「 ~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 實際是在做什麼事情。

若是指令派的使用者,無論是觀念或是資料的取用,在之後的操作一定會用到,也請多加留意!