前面一篇文章介紹了本地倉庫的一系列操作,下面我們將進一步了解Git的工作原理,介紹Git對象模型。
剛開始使用Git的時候,對Git對象模型、工作原理並不理解,但是經過一段時間的使用、熟悉之后,然后再來理解這些內容就比較容易了。
下面開始介紹Git對象,然后通過一個實例展示Git對象模型。
Git對象
在Git系統中有四種類型的對象,所有的Git操作都是基於這四種類型的對象。
- "blob":這種對象用來保存文件的內容。
- "tree":可以理解成一個對象關系樹,它管理一些"tree"和 "blob"對象。
- "commit":只指向一個"tree",它用來標記項目某一個特定時間點的狀態。它包括一些關於時間點的元數據,如時間戳、最近一次提交的作者、指向上次提交(初始commit沒有這一項)。
- "tag":給某個提交(commit) 增添一個標記。
SHA1哈希值
上面我們介紹了Git對象,在Git系統中,每個Git對象都有一個特殊的ID來代表這個對象,這個特殊的ID就是我們所說的SHA1哈希值。
SHA1哈希值是通過SHA1算法(SHA算法家族的一種)計算出來的哈希值,對於內容不同的對象,會有不同的SHA1哈希值。如果你讀過前面一篇文章,就肯定還記得我們是怎么根據commit id撤銷更新的,這里的commit id就是一個SHA1哈希值。
Git對象模型實例
下面我們通過一個例子來認識一下上面的四種對象,為了更加清楚,這里將一步步展示經過一系列操作后對象的關系變化。
第一步:新建一個倉庫,添加一個"calc.py"的文件
通過"git log --pretty=raw"可以得到每個commit的SHA1哈希值,也可以得到這個commit對應的tree的哈希值。
所以,一個commit對象一般包含以下信息:
- 代表commit的哈希值
- 指向tree 對象的哈希值
- 作者
- 提交者
- 注釋
在Git對象模型的研究中,有一個很有用的命令"git cat-file",可以通過這個命令查詢特定對象的信息:
- git cat-file -t key:通過一個對象的哈希值可以通過這條命令查看對象的類型(blob、tree、commit或tag)
- git cat-file -p key:通過對象的哈希值可以查看這個對象的內容
下面我們看一下在這次提交中commit、tree對象的類型和內容。這里可以看到,在這一次的commit中tree對象的內容指向一個blob對象。
同樣,我們可以查看blob對象的類型和內容,這里可以看到blob的內容就是我們要提交的文件的內容。
所以,根據上面的一些數據,我們可以看到在這一次的提交中產生了三個對象,同時看到了commit、tree、blob三個對象的關系如下:
第二步:更新"calc.py"文件,添加sub函數
繼續使用"git log --pretty=raw"查看commit log。
同樣通過"git cat-file"我們可以看到每一個對象的類型和內容,這里就不一步一步上圖了,直接給出所有的對象關系。
這里需要注意的一點,Perforce、SVN和CVS屬於"增量文件系統" (Delta Storage systems),它們每次只存儲提交(commit)之間的差異。而對於Git,它會把你的每次提交的文件的全部內容(snapshot)都會記錄下來。
第三步:增加一個"app.py";增加"advance"文件夾,包括"__init__.py"和"calc.py"
$ git log --pretty=raw commit 4ea6c317a67e73b0befcb83c36b915c1481f2efe tree 2735b08cab34af7732970fec95a1b3e718628d53 parent c2163e267380f71373f29f922e7089abbb741772 author WilberTian <Wilber***.com> 1419771391 +0800 committer WilberTian <Wilber***.com> 1419771391 +0800 add app.py, __init__.py and calc.py
同樣的方式,我們可以得到一張更復雜的對象關系圖:
總結
Git對象模型就像是Git系統特有的文件系統,以特定的方式存儲更新的內容、元數據以及版本歷史信息。
通過Git對象模型進一步熟悉了Git的工作原理,相信有了這些知識,我們就可以分析git命令背后到底發生了什么。