探索.git目錄


.git目錄

下面就開始進入.git目錄,通過“ls”命令可以看到.git目錄中的文件和子目錄:

對於這些文件和目錄,下面給出了一些基本的描述。

  • hooks:這個目錄存放一些shell腳本,可以設置特定的git命令後觸發相應的腳本;在搭建gitweb系統或其他git託管系統會經常用到hook script
  • info:包含倉庫的一些信息
  • logs:保存所有更新的引用記錄
  • objects:所有的Git對象都會存放在這個目錄中,對象的SHA1哈希值的前兩位是文件夾名稱,後38位作爲對象文件名
  • refs:這個目錄一般包括三個子文件夾,heads、remotes和tags,heads中的文件標識了項目中的各個分支指向的當前commit
  • COMMIT_EDITMSG:保存最新的commit message,Git系統不會用到這個文件,只是給用戶一個參考
  • config:這個是GIt倉庫的配置文件
  • description:倉庫的描述信息,主要給gitweb等git託管系統使用
  • index:這個文件就是我們前面提到的暫存區(stage),是一個二進制文件
  • HEAD:這個文件包含了一個檔期分支(branch)的引用,通過這個文件Git可以得到下一次commit的parent
  • ORIG_HEAD:HEAD指針的前一個狀態

Git引用

Git中的引用是一個非常重要的概念,對於理解分支(branch)、HEAD指針以及reflog非常有幫助。

Git系統中的分支名、遠程分支名、tag等都是指向某個commit的引用。比如master分支,origin/master遠程分支,命名爲V1.0.0.0的tag等都是引用,它們通過該保存某個commit的SHA1哈希值指向某個commit

重新認識HEAD

HEAD也是一個引用,一般情況下間接指向你當前所在的分支的最新的commit上。HEAD跟Git中一般的引用不同,它並不包含某個commit的SHA1哈希值,而是包含當前所在的分支,所有HEAD直接執行當前所在的分支,然後間接指向當前所在分支的最新提交。

爲了更形象的解釋上面的描述,我們首先查看“.git/HEAD”的內容:

這就表示HEAD是一個指向master分支的引用,然後我們可以根據引用路徑打開“refs/heads/master”文件,內容如下:

 

根據前面一片文章的介紹,我們通過這個哈希值查看對象的類型和雷人,可以看到這個哈希值對應着一個commit,並通過“git log”可以發現這個commit就是master分支上最新的提交。

所以可以看到,所有的內容都是環環相扣的,我們通過HEAD找到一個當前分支,然後通過當前分支的引用找到最新的commit,然後通過commit可以找到整個對象關係模型,看下圖:

引用和分支

直到現在我們都沒有開始介紹分支(branch),先大概展示一下引用和分支的關係。

假設我們現在除了master分支,又創建了一個release-1.0.0.1的分支,再次查看“.git/refs/heads/”目錄,可以看到除了master文件之外,又多了一個release-1.0.0.1文件,查看該文件的內容也是一個哈希值。

通過“git show-ref --heads”命令就可以查看所有的頭,這些都是HEAD的候選值:

HEAD文件的內容是commit的分支,當我們把分支切換到release-1.0.0.1的時候,HEAD文件的內容也會相應的變成:

ref: refs/heads/release-1.0.0.1

日誌

我們進入“.git/logs”文件夾,可以看到這個文件夾也有一個HEAD文件和refs目錄,這些就是記錄commit歷史記錄的地方。我們可以通過commit的哈希值,把repo退到一個指定的狀態。

Git索引index

前面文章我們也提到過index/stage,就是更新的暫存區,下面來看看index文件。

index(索引)是一個存放了已排序的路徑的二進制文件,並且每個路徑都對應一個SHA1哈希值。在Git系統中,可以通過“git ls-files --stage”來顯示index文件的內容:

 

從命令的輸出可以看到,所有的記錄都對應倉庫中的文件(包含全路徑)。上面顯示的哈希值就是abc.txt的blob對象的哈希值。

現在我們更新abc.txt文件,並通過“git add”添加到暫存區,這時發現index中的abc對象的哈希值已經變化了。

對象的存儲

前面提到所有的Git對象都會存放在“.git/objects”目錄中,對象SHA1哈希值的前兩位是文件夾名稱,後38位作爲對象文件名。下面是之前提到的master最新的commit對象的哈希值:

63a6ea8475b47078dee14ea8ff2c8731927ffbbf

在Git系統中有兩種對象存儲的方式,鬆散對象存儲和打包對象存儲

鬆散對象(loose object)

鬆散對象存儲就是前面提到的,每一個對象都被寫入一個單獨文件中,對象SHA1哈希值的前兩位是文件夾名稱,後38位作爲對象文件名。

打包對象(packed object)

對應鬆散存儲,把每個文件的每個版本都作爲一個單獨的對象,它的效率比較低,而且浪費空間。所以就有了通過打包文件(packfile)的存儲方式。

Git使用打包文件(packfile)去節省空間。在這個格式中,Git只會保存第二個文件中改變的部分,然後用一個指針指向相似的那個文件。

一般Git系統會自動完成打包的工作,在已經發生過打包的Git倉庫中,object/pack目錄下回成對出現很多“pack-***.idx”和“pack-***.pak”文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章