-
A1. 附錄 A:其他環境中的 Git
- A1.1 圖形介面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 摘要
-
A2. 附錄 B:在您的應用程式中嵌入 Git
-
A3. 附錄 C:Git 命令
10.3 Git 內部 - Git 參考
Git 參考
如果您想查看從提交(例如 `1a410e`)可訪問的儲存庫歷史記錄,您可以執行類似 `git log 1a410e` 的命令來顯示該歷史記錄,但您仍然必須記住 `1a410e` 是您想要用作歷史記錄起點的提交。相反,如果您有一個檔案,可以將該 SHA-1 值以一個簡單的名稱儲存,這樣您就可以使用該簡單的名稱而不是原始 SHA-1 值,那就更容易了。
在 Git 中,這些簡單的名稱稱為「參考」(references)或「refs」;您可以在 `.git/refs` 目錄中找到包含這些 SHA-1 值的檔案。在目前的專案中,這個目錄不包含任何檔案,但它確實包含一個簡單的結構。
$ find .git/refs
.git/refs
.git/refs/heads
.git/refs/tags
$ find .git/refs -type f
要建立一個新的參考,以幫助您記住最新的提交位置,您可以在技術上執行如下簡單的操作:
$ echo 1a410efbd13591db07496601ebc7a059dd55cfe9 > .git/refs/heads/master
現在,您可以使用剛剛建立的 head 參考,而不是 Git 命令中的 SHA-1 值。
$ git log --pretty=oneline master
1a410efbd13591db07496601ebc7a059dd55cfe9 Third commit
cac0cab538b970a37ea1e769cbbde608743bc96d Second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit
不建議您直接編輯參考檔案;相反,Git 提供了更安全的 `git update-ref` 命令來執行此操作,如果您想更新參考。
$ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
這基本上就是 Git 中分支的概念:一個簡單的指標或參考,指向工作線的開頭。要建立回到第二個提交的分支,您可以執行以下操作:
$ git update-ref refs/heads/test cac0ca
您的分支將只包含該提交開始之後的工作。
$ git log --pretty=oneline test
cac0cab538b970a37ea1e769cbbde608743bc96d Second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit
現在,您的 Git 資料庫在概念上看起來像這樣:

當您執行像 git branch <branch>
這樣的指令時,Git 基本上會執行 update-ref
指令,將您目前所在分支的最後一次提交的 SHA-1 值,加入到您想要建立的任何新參考中。
HEAD
現在的問題是,當您執行 git branch <branch>
時,Git 如何知道最後一次提交的 SHA-1 值?答案是 HEAD 檔案。
通常,HEAD 檔案是一個指向您目前所在分支的符號參考。所謂符號參考,是指它不像一般的參考,而是包含指向另一個參考的指標。
然而,在某些罕見的情況下,HEAD 檔案可能包含 Git 物件的 SHA-1 值。當您檢出一個標籤、提交或遠端分支時,就會發生這種情況,這會將您的儲存庫置於「分離 HEAD」狀態。
如果您查看該檔案,通常會看到類似這樣的內容
$ cat .git/HEAD
ref: refs/heads/master
如果您執行 git checkout test
,Git 會更新檔案使其看起來像這樣
$ cat .git/HEAD
ref: refs/heads/test
當您執行 git commit
時,它會建立提交物件,並將該提交物件的父物件指定為 HEAD 中參考指向的任何 SHA-1 值。
您也可以手動編輯此檔案,但有一個更安全的指令可以做到這一點:git symbolic-ref
。您可以使用此指令讀取 HEAD 的值
$ git symbolic-ref HEAD
refs/heads/master
您也可以使用相同的指令設定 HEAD 的值
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
ref: refs/heads/test
您不能在 refs 樣式之外設定符號參考
$ git symbolic-ref HEAD test
fatal: Refusing to point HEAD outside of refs/
標籤
我們剛剛討論完 Git 的三個主要物件類型(blobs、trees 和 commits),但還有第四個。tag 物件非常像提交物件 — 它包含標籤者、日期、訊息和指標。主要區別在於標籤物件通常指向提交,而不是樹狀結構。它就像一個分支參考,但它永遠不會移動 — 它始終指向相同的提交,但會給它一個更友好的名稱。
如Git 基礎中所討論的,標籤有兩種:附註標籤和輕量標籤。您可以執行類似這樣的指令來建立輕量標籤
$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d
這就是輕量標籤的全部 — 一個永遠不會移動的參考。但是,附註標籤更複雜。如果您建立一個附註標籤,Git 會建立一個標籤物件,然後寫入一個指向該物件的參考,而不是直接指向提交。您可以透過建立一個附註標籤(使用 -a
選項)來查看此情況
$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'Test tag'
這是它建立的物件 SHA-1 值
$ cat .git/refs/tags/v1.1
9585191f37f7b0fb9444f35a9bf50de191beadc2
現在,對該 SHA-1 值執行 git cat-file -p
$ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
object 1a410efbd13591db07496601ebc7a059dd55cfe9
type commit
tag v1.1
tagger Scott Chacon <schacon@gmail.com> Sat May 23 16:48:58 2009 -0700
Test tag
請注意,該物件條目指向您標記的提交 SHA-1 值。另請注意,它不需要指向提交;您可以標記任何 Git 物件。例如,在 Git 原始碼中,維護者已將其 GPG 公鑰作為 blob 物件新增,然後對其進行標記。您可以在 Git 儲存庫的複製版本中執行此操作來查看公鑰
$ git cat-file blob junio-gpg-pub
Linux 核心儲存庫也有一個非提交指向的標籤物件 — 建立的第一個標籤指向導入原始碼的初始樹狀結構。
遠端
您將看到的第三種類型的參考是遠端參考。如果您新增一個遠端並推送至該遠端,Git 會將您上次推送至該遠端的每個分支的值儲存在 refs/remotes
目錄中。例如,您可以新增一個名為 origin
的遠端,並將您的 master
分支推送至該遠端
$ git remote add origin git@github.com:schacon/simplegit-progit.git
$ git push origin master
Counting objects: 11, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 716 bytes, done.
Total 7 (delta 2), reused 4 (delta 1)
To git@github.com:schacon/simplegit-progit.git
a11bef0..ca82a6d master -> master
然後,您可以透過檢查 refs/remotes/origin/master
檔案,查看您上次與伺服器通訊時 origin
遠端上的 master
分支是什麼
$ cat .git/refs/remotes/origin/master
ca82a6dff817ec66f44342007202690a93763949
遠端參考與分支(refs/heads
參考)的主要區別在於,它們被視為唯讀。您可以 git checkout
到一個遠端參考,但 Git 不會將 HEAD 符號參考到它,因此您永遠不會使用 commit
指令更新它。Git 將它們作為書籤來管理,這些書籤指向這些分支在這些伺服器上的最後已知狀態。