1-分離 HEAD

1-1-說明

1-1-1-HEAD 移動

在接觸 git 的更多進階的主題之前,我們先學習用不同的方法在你的 project 中的 commit tree 上面移動。
一旦能夠熟練地在 commit tree 中隨意地移動,你使用其它的 git 指令也會更厲害!

1-1-2-HEAD

我們首先看一下 “HEAD”,HEAD 是一個 reference,它是指向目前所 checkout 的 commit,基本上,其實就是你目前所在的 commit。
在 commit tree 中,HEAD 總是指向最近的一次commit。大部份 git 的指令如果要修改 commit tree 的狀態的話,都會先改變 HEAD 所指向的 commit。
HEAD 通常指向一個 branch 的名稱(比如 bugFix)。當你 commit 的時候,改變了 bugFix 的狀態,這一個變化可以從 HEAD 的改變中看到。

在實際的例子中。我們將會觀察 commit 前後 HEAD 的位置。
Git 練習遊戲_learngitbranching-2-進階篇-1-在 git 中前後移動-1

Git 練習遊戲_learngitbranching-2-進階篇-1-在 git 中前後移動-2

1-1-3-分離 HEAD

分離 HEAD 就是讓其指向一個 commit 而不是 branch 的名稱。這是指令執行之前的樣子:
HEAD -> master -> C1
Git 練習遊戲_learngitbranching-2-進階篇-1-在 git 中前後移動-3

Git 練習遊戲_learngitbranching-2-進階篇-1-在 git 中前後移動-4

1-2-解題

想要完成這一個關卡,從 bugFix 分離出 HEAD 並且讓它指向一個 commit。
通過 hash 值可以指定 commit。每個 commit 的 hash 值顯示在各自的圓圈中。
Git 練習遊戲_learngitbranching-2-進階篇-1-在 git 中前後移動-5

Git 練習遊戲_learngitbranching-2-進階篇-1-在 git 中前後移動-6


2-相對引用(^)

2-1-介紹

2-1-1-相對引用

如果要在 git 中移動,透過指定 commit 的 hash 值的方式會變得比較麻煩。在實際例子中,你的終端機上面不會出現漂亮且具備視覺效果的 commit tree,所以你不得不用 git log 來查詢 hash 值。

另外,hash 值的長度在真實的 git 環境中很長。舉個例子,前一個關卡的介紹中的 commit 的 hash 值是 fed2da64c0efc5293610bdd892f82a58e8cbc5d8。舌頭不要打結了…

幸運的是,git 對於處理 hash 值很有一套。你只需要提供能夠唯一辨識出該 commit 的前幾個字元就可以了。所以,我可以只輸入 fed2 而不是上面的一長串字元。

我說過,透過 hash 值來指定 commit 不是很方便,所以 git 加入了相對引用。這個就很厲害了!
使用相對引用,你可以從一個易於記憶的地方(比如說 branch 名稱 bugFix 或 HEAD)開始工作。
相對引用非常好用,這裡我介紹兩個簡單的用法:

  • 使用 ^ 向上移動一個 commit
  • 使用 ~<num> 向上移動多個 commit

首先看看插入(^)這一個符號。把這個符號接在某一個 reference 後面,就表示你告訴 git 去找到該 reference 所指向的 commit 的 parent commit。

所以 master^ 相當於 “ master 的 parent commit”。
master^^master 的 grandparent commit(往前推兩代)

切換到 master的 parent commit
Git 練習遊戲_learngitbranching-2-進階篇-2-相對引用(^)-1

Git 練習遊戲_learngitbranching-2-進階篇-2-相對引用(^)-2

你也可以把 HEAD 當作相對引用。以下指令使用 HEAD 在 commit tree 中向上移動數次。

Git 練習遊戲_learngitbranching-2-進階篇-2-相對引用(^)-3

2-2-解題

要完成這一關,切換到 bugFix 的 parent commit。這會分離出 HEAD
如果你願意的話,透過直接指定 hash 值的方式也可以過關,但是還是試試看相對引用吧!
Git 練習遊戲_learngitbranching-2-進階篇-2-相對引用(^)-4

Git 練習遊戲_learngitbranching-2-進階篇-2-相對引用(^)-5


3- 相對引用二(~)

3-1-介紹

3-1-1- ~ 符號

假設需要在 commit tree 中向上移動多個 commit。使用太多 ^ 會非常討人厭,所以 Git 也加入了波浪( ~)符號。
波浪符號後面可以選擇一個數字(你也可以不選擇),該數字可以告訴 Git 我要向上移動多少個 commit 。舉個例子
Git 練習遊戲_learngitbranching-2-進階篇-~符號-1

使用指令 git chekcout HEAD~4 ,讓目前的 HEAD 後對四格 (目前的 commit 也要算進一個)。
Git 練習遊戲_learngitbranching-2-進階篇-~符號-2

3-1-2-Branch forcing

你現在是相對引用的高手了,現在用它來實際做點事情。
我使用相對引用最多的就是移動分支。你可以使用 -f 選項直接讓分支指向另一個 commit。舉個例子:

3-2-解題

要完成這一關,移動 HEAD,master 和 bugFix 到目標所示的位置。
Git 練習遊戲_learngitbranching-2-進階篇-~符號-3

可以不用透過 HEAD 切到指定的分支, 透過直接指定分支命與 -f 參數,來操作指定退的格數或是當定的 coomit hash 編號上。

git branch -f master C6
將 master 分支直接指定到 C6 的 HASH 編號上。
Git 練習遊戲_learngitbranching-2-進階篇-~符號-4

git checkout HEAD~1
直接指定 HEAD 退一格,不用帶 -f 參數。
Git 練習遊戲_learngitbranching-2-進階篇-~符號-5

git branch -f bugFix HEAD~1
Git 練習遊戲_learngitbranching-2-進階篇-~符號-6


4-在 git 中取消修改

4-1-介紹

4-1-1-取消 git 的修改

在 git 裡面取消修改的方法很多。和 commit 一樣,在 git 裡面取消修改同時具有底層的部份(暫存一些獨立的文件或者片段)和高層的部份(修改是如何被取消)。我們主要講的重點是後者。

在 git 裡主要用兩種方法來取消修改,一種是 git reset,另外一種是 git revert。讓我們在下一個對話視窗中逐一瞭解它們。

4-1-2-Git Reset

git reset 把分支的參考點退回到上一個 commit 來取消修改。你可以認為這是在”重寫歷史”。git reset 往回移動 branch,原來的 branch 所指向的 commit 好像從來沒有存在過一樣。
Git 練習遊戲_learngitbranching-2-進階篇-1

使用指令 git reset HEAD~1 ,譠 commit 退一格。
Git 練習遊戲_learngitbranching-2-進階篇-2

4-1-3-Git Revert

雖然在你的 local branch 中使用 git reset 很方便,但是這種「改寫歷史」的方法對別人的 remote branch 是無效的哦!
為了取消修改並且把這個狀態分享給別人,我們需要使用 git revert。舉個例子
Git 練習遊戲_learngitbranching-2-進階篇-3

使用指令 git revert HEAD ,在當前的 commit 點另外在長出同樣內容的 commit。
Git 練習遊戲_learngitbranching-2-進階篇-4

4-2-解題

要完成這一關,分別取消 local branch 和 pushed branch 上的最近的一次 commit。
記住 pushed 是一個 remote branch,local 是一個 local branch,有了這麼明顯的提示應該知道要用哪種方法了吧?
Git 練習遊戲_learngitbranching-2-進階篇-5

Git 練習遊戲_learngitbranching-2-進階篇-6