← 上一章:【冷知識】為什麼大家都說在 Git 開分支「很便宜」? 下一章:【狀況題】我可以從過去的某個 Commit 再長一個新的分支出來嗎? →
【冷知識】Git 怎麼知道現在是在哪一個分支?
當執行 git branch
指令的時候,可以看到目前所有的分支列表:
$ git branch
cat
dog
* master
看得出來目前共有 3 個分支,前面那個 *
號表示目前是處於 master
這個分支。那 Git 是在哪裡記錄這個資訊呢?
在 .git 目錄裡藏了很多有趣的東西,我們會在「【超冷知識】在 .git 目錄裡有什麼東西?」章節有更詳細的介紹。其中在 .git 目錄裡有一個名字叫做 HEAD
的檔案:
看看裡面是什麼東西:
$ cat .git/HEAD
ref: refs/heads/master
還記得 refs/heads/master
這個檔案的內容嗎?如果忘了可參閱「【冷知識】為什麼大家都說在 Git 開分支「很便宜」?」的說明。
其實 HEAD 的內容就這麼簡單,它就是記錄著目前指向的分支。我們來試著切換分支看看:
$ git checkout cat
Switched to branch 'cat'
然後再看一次 HEAD
檔案的內容:
$ cat .git/HEAD
ref: refs/heads/cat
在切換分支的時候,HEAD 的內容也會跟著變化。
【冷知識】HEAD 也有縮寫喔
從 Git 1.8.5 之後的版本,在使用 Git 的時候,可以用 @
來代替 HEAD,例如原本的指令是這樣:
$ git reset HEAD^
可以用 @
來替代:
$ git reset @^
但這樣有沒有比原來使用 HEAD 來得清楚,就見人見智了。
ORIG_HEAD 是什麼東西?
在 .git 目錄裡除了剛剛說的 HEAD 檔案之外,還有另一個叫做 ORIG_HEAD
的檔案,當你在做一些比較「危險」的操作(例如像 merge
、rebase
或 reset
之類的),Git 就會把 HEAD 的狀態存放在這裡,讓你隨時可以跳回危險動作之前的狀態。
雖然 git reflog
指令也可以查到相關資訊,但 Reflog 的資料比較雜一點,這個 ORIG_HEAD
會更方便的讓你找到最近一次危險動作之前的 SHA-1 值。舉例來說:
$ git log --oneline
b174a5a (HEAD -> cat) add cat 2
c68537b add cat 1
e12d8ef (master) add database.yml in config folder
85e7e30 add hello
657fce7 add container
abb4f43 update index page
cef6e40 create index page
cc797cd init commit
然後我故意使用 hard 模式執行 Reset 指令,倒退一步:
$ git reset HEAD^ --hard
HEAD is now at c68537b add cat 1
看一下 ORIG_HEAD 的內容:
$ cat .git/ORIG_HEAD
b174a5a95a75c963617409d2fdb514c210d86ba6
它記錄的這個內容,正是進行 reset 指令前的 SHA-1 值 b174a5a
,所以如果想要取消剛剛這次 reset
:
$ git reset ORIG_HEAD --hard
HEAD is now at b174a5a add cat 2
直接使用 reset 指令到 ORIG_HEAD
就能退回 reset 之前的狀態了。再來試一下合併,首先,我先切換到 master
分支:
$ git checkout master
Switched to branch 'master'
接著準備合併 cat
分支:
$ git merge cat
Updating e12d8ef..b174a5a
Fast-forward
cat1.html | 0
cat2.html | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 cat1.html
create mode 100644 cat2.html
沒有意外的使用快轉模式(Fast Forward)進行合併。這時候的狀態應該像這樣:
看一下現在的 ORIG_HEAD
的內容:
$ cat .git/ORIG_HEAD
e12d8ef0e8b9deae8bf115c5ce51dbc2e09c8904
看得出來它指向哪裡嗎?它正指向著合併前的那個 Commit,所以如果想取消這次的合併:
$ git reset ORIG_HEAD --hard
HEAD is now at e12d8ef add database.yml in config folder
剛剛那次的合併就取消了。這個技巧用在取消 Rebase 合併的時候相當方便,詳情請見「另一種合併方式(使用 rebase)」章節說明。
← 上一章:【冷知識】為什麼大家都說在 Git 開分支「很便宜」? 下一章:【狀況題】我可以從過去的某個 Commit 再長一個新的分支出來嗎? →
Comments