溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Git工程開發(fā)實踐(二)——Git內(nèi)部實現(xiàn)機制

發(fā)布時間:2020-02-27 04:22:09 來源:網(wǎng)絡 閱讀:3835 作者:天山老妖S 欄目:軟件技術

Git工程開發(fā)實踐(二)——Git內(nèi)部實現(xiàn)機制

一、Git倉庫內(nèi)部實現(xiàn)簡介

Git本質上是一個內(nèi)容尋址(content-addressable)的文件系統(tǒng),根據(jù)文件內(nèi)容的SHA-1哈希值來定位文件。Git核心部分是一個簡單的鍵值對數(shù)據(jù)庫(key-value data store)。向Git數(shù)據(jù)庫插入任意類型的內(nèi)容,會返回一個鍵值,通過返回的鍵值可以在任意時刻再次檢索(retrieve)插入的內(nèi)容。通過底層命令hash-object可以將任意數(shù)據(jù)保存到.git目錄并返回相應的鍵值。
Git包含一套面向版本控制系統(tǒng)的工具集,包括高級命令和底層命令。高級命令主要由用戶使用,底層命令可以窺探Git內(nèi)部的工作機制,但多數(shù)底層命令并不面向最終用戶,更適合作為新命令和自定義腳本的組成部分。
使用git init創(chuàng)建倉庫時,Git會創(chuàng)建一個.git目錄,其目錄結構如下:
Git工程開發(fā)實踐(二)——Git內(nèi)部實現(xiàn)機制
A、description文件僅供GitWeb程序使用。
B、config文件包含項目特有的配置選項。
C、info目錄包含一個全局性排除(global exclude)文件,用于放置不希望被記錄在.gitignore文件中的忽略模式(ignored patterns)。
D、hooks目錄包含客戶端或服務端的鉤子腳本(hook scripts)。
E、objects目錄存儲所有數(shù)據(jù)內(nèi)容,內(nèi)有info、pack子目錄。
F、refs目錄存儲指向數(shù)據(jù)(分支)的提交對象的指針。
G、HEAD文件指示目前被檢出的分支。
H、index(尚待創(chuàng)建)文件保存暫存區(qū)信息。
objects、refs、HEAD、index是Git倉庫的四個核心部分。

二、Git對象

1、Git對象簡介

Git對象分為四種:數(shù)據(jù)對象(blob)、樹對象(tree)、提交對象(commit)、標簽對象(tag)。Git文件系統(tǒng)的設計思路與linux文件系統(tǒng)相似,即將文件的內(nèi)容與文件的屬性分開存儲,文件內(nèi)容存儲在文件系統(tǒng)中,文件名、所有者、權限等文件屬性信息則另外開辟區(qū)域進行存儲。
Git利用SHA-1加密算法對其管理的每一個文件生成一個唯一的16進制的40個字符長度的SHA-1哈希值來唯一標識對象。如果文件不變化,SHA-1哈希值不會改變;如果文件改變,會生成新的SHA-1哈希值。40位字符SHA-1哈希值的前兩個字符作為目錄名,后38個字符作為文件名,標識生成的Git對象。
Git對象的SHA-1哈希值計算公式如下:

header = "<type> " + content.length + "\0"
hash = sha1(header + content)

Git在計算對象hash時,首先會在對象頭部添加一個header。header由3部分組成:第一部分表示對象的類型,可以取值blob、tree、commit以分別表示數(shù)據(jù)對象、樹對象、提交對象;第二部分是數(shù)據(jù)的字節(jié)長度;第三部分是一個空字節(jié),用來將header和content分隔開。將header添加到content頭部后,使用sha1算法計算出一個40位的hash值。
在手動計算Git對象的hash時需要注意:
A、header中第二部分關于數(shù)據(jù)長度的計算,一定是字節(jié)的長度而不是字符串的長度;
B、header + content的操作并不是字符串級別的拼接,而是二進制級別的拼接。
各種Git對象的hash方法相同,不同的在于:
A、頭部類型不同,數(shù)據(jù)對象是blob,樹對象是tree,提交對象是commit;
B、數(shù)據(jù)內(nèi)容不同,數(shù)據(jù)對象的內(nèi)容可以是任意內(nèi)容,而樹對象和提交對象的內(nèi)容有固定的格式。
git cat-file可以用來實現(xiàn)所有Git對象的讀取,包括數(shù)據(jù)對象、樹對象、提交對象的查看。
git cat-file -p [hash-key] 可以查看已經(jīng)存在的object對象內(nèi)容
git cat-file -t [hash-key] 可以查看已經(jīng)存在的object對象類型

2、Git數(shù)據(jù)對象

2.1Git數(shù)據(jù)對象簡介

數(shù)據(jù)對象通常用于存儲文件的內(nèi)容,但不包括文件名、權限等信息。數(shù)據(jù)對象和其對應文件的所在路徑、文件名是否改被更改都完全沒有關系。
Git會根據(jù)文件內(nèi)容計算出一個SHA-1 hash值,以hash值作為索引將文件存儲在Git文件系統(tǒng)中。由于相同的文件內(nèi)容的hash值是一樣的,因此Git將相同內(nèi)容的文件只會存儲一次。git hash-object命令可以用來計算文件內(nèi)容的hash值,并將生成的數(shù)據(jù)對象存儲到Git文件系統(tǒng)中。
echo -en "hello,git" | git hash-object --stdin
f28ffa36cdf69904e516babfdb3005e108dddfb7
在echo后面使用-n選項,用來阻止自動在字符串末尾添加換行符,否則會導致實際傳給git hash-object是hello,git\n
數(shù)據(jù)對象查看:
git show + 對象名(SHA1哈希值)

2.2Git數(shù)據(jù)對象的SHA-1哈希值計算

數(shù)據(jù)對象的內(nèi)容格式如下:

blob <content length><NULL><content>

使用git hash-object計算文本的SHA1哈希值
echo -en "hello,git" | git hash-object --stdin
f28ffa36cdf69904e516babfdb3005e108dddfb7
使用openssl計算文本的SHA1哈希值:
echo -en "blob 9\0hello,git" | openssl sha1
(stdin)= f28ffa36cdf69904e516babfdb3005e108dddfb7
如果文本中有中文時,必須注意數(shù)據(jù)長度的計算是字節(jié)數(shù)而不是字符數(shù)??梢允褂妹畈榭次谋镜淖止?jié)數(shù):
echo -n "中文" | wc -c

2.3Git數(shù)據(jù)對象的存取
git init Test //初始化一個版本庫
cd Test //進入Test
find .git/objects //查找.git/objects目錄下的內(nèi)容

Git對objects目錄進行初始化,并創(chuàng)建pack和info目錄,但均為空。
echo 'test content' | git hash-object -w --stdin //向Git數(shù)據(jù)庫存入文本
d670460b4b4aece5915caf5c68d12f560a9fe3e4 //返回的鍵值
-w選項指示hash-object命令存儲數(shù)據(jù)對象;若不指定此選項,則上述命令僅返回對應的鍵值。
--stdin選項則指示上述命令從標準輸入讀取內(nèi)容,若不指定此選項,則須在命令尾部給出待存儲文件的路徑。
命令輸出一個長度為40個字符的校驗和,是一個SHA-1哈希值,一個將待存儲的數(shù)據(jù)外加一個頭部信息(header)一起做SHA-1校驗運算而得的校驗和。
find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
可以在objects目錄下看到一個文件。 Git存儲內(nèi)容的方式是一個文件對應一條內(nèi)容,用內(nèi)容加上特定頭部信息一起的SHA-1校驗和為文件命名。校驗和的前兩個字符用于命名子目錄,余下的38個字符則用作文件名。
可以通過cat-file命令從Git數(shù)據(jù)庫取回數(shù)據(jù)。指定-p選項可指示cat-file命令自動判斷內(nèi)容的類型,并顯示格式友好的內(nèi)容:
git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content

2.4Git版本控制原理的實現(xiàn)

通過對一個文件進行簡單的版本控制揭示Git版本控制的原理。首先,創(chuàng)建一個新文件并將其內(nèi)容存入Git數(shù)據(jù)庫。

echo "version 1" > test //寫入test文件內(nèi)容
git hash-object -w test  //存儲test文件到Git數(shù)據(jù)庫

83baae61804e65cc73a7201a7252750c76066a30

echo 'version 2' > test  //寫入test文件新的內(nèi)容
git hash-object -w test  //再次將修改后的test文件存儲到Git數(shù)據(jù)庫

1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
Git數(shù)據(jù)庫記錄了test文件的兩個不同版本。
find .git/objects -type f

.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a

恢復test文件到第一個版本:

git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test   
cat test   //讀取test文件內(nèi)容

version 1
恢復test文件到第二個版本:

git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test
cat test  //讀取test文件內(nèi)容

version 2
上述對文件的版本控制中,記住文件的每一個版本所對應的SHA-1值并不現(xiàn)實,并且文件名并沒有被保存。
利用cat-file -t命令,可以查看Git內(nèi)部存儲的任何對象類型,只要給定對象的SHA-1值。
git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
blob
通過每一個數(shù)據(jù)對象的hash值,可以訪問Git文件系統(tǒng)中的任意數(shù)據(jù)對象,但記住數(shù)據(jù)對象的SHA-1哈希值顯然是不現(xiàn)實的。數(shù)據(jù)對象只是解決了文件內(nèi)容存儲的問題,而文件名的存儲則需要通過樹對象實現(xiàn)。

3、Git樹對象

3.1Git對象簡介

樹對象包含指向數(shù)據(jù)對象或是其它樹對象的多個指針,用來表示內(nèi)容之間的目錄層次關系。
Git所有內(nèi)容均以樹對象和數(shù)據(jù)對象的形式存儲,其中樹對象對應UNIX中的目錄項,數(shù)據(jù)對象對應inodes或文件內(nèi)容。 一個樹對象包含一條或多條樹對象記錄(tree entry),每條樹對象記錄含有一個指向數(shù)據(jù)對象或者子樹對象的SHA-1指針以及相應的模式、類型、文件名信息。
某項目當前對應的最新樹對象可以使用如下命令查看:
git cat-file -p master^{tree}
master^{tree}語法表示master分支上最新的提交所指向的樹對象。 目錄(所對應的樹對象記錄)并不是一個數(shù)據(jù)對象,而是一個指針,其指向的是另一個樹對象。
樹對象查看:
git show + 對象名/git ls-tree + 對象名
git ls-files --stage命令可以查看暫存區(qū)的內(nèi)容。

3.2Git樹對象的SHA1哈希值計算

樹對象的內(nèi)容格式如下:

tree <content length><NUL><file mode> <filename><NUL><item sha>...

item sha部分是二進制形式的sha1碼,而不是十六進制形式的sha1碼。
git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30? test.txt
首先使用xxd把83baae61804e65cc73a7201a7252750c76066a30轉換成為二進制形式,并將結果保存為sha1.txt以方便后面做追加操作。

echo -en "83baae61804e65cc73a7201a7252750c76066a30" | xxd -r -p > sha1.txt

構造content部分,并保存至文件content.txt

echo -en "100644 test.txt\0" | cat - sha1.txt > content.txt

計算content的長度
cat content.txt | wc -c
生成SHA-1
echo -en "tree 36\0" | cat - content.txt | openssl sha1
(stdin)= d8329fc1cc938780ffdd9f94e0d364e0ea74f579

3.3Git樹對象生成

Git根據(jù)某一時刻暫存區(qū)(即index文件)所表示的狀態(tài)創(chuàng)建并記錄一個對應的樹對象,如此重復便可依次記錄(某個時間段內(nèi))一系列的樹對象。 因此,為創(chuàng)建一個樹對象,首先需要通過暫存一些文件來創(chuàng)建一個暫存區(qū)。通過update-index為一個單獨文件(test.txt文件)的首個版本創(chuàng)建一個暫存區(qū)。 利用update-index命令,可以把test文件的首個版本加入一個新的暫存區(qū)。

git update-index --add --cacheinfo 100644 \
  83baae61804e65cc73a7201a7252750c76066a30 test

--add表示新增文件名,如果第一次添加某一文件名,必須使用此選項;--cacheinfo mode object path是要添加的數(shù)據(jù)對象的模式、hash值和路徑,path意味著為數(shù)據(jù)對象不僅可以指定單純的文件名,也可以使用路徑。另外要注意的是,使用git update-index添加完文件后,一定要使用git write-tree寫入到Git文件系統(tǒng)中,否則只會存在于暫存區(qū)。
指定的文件模式為100644,表明是一個普通文件。 其它選擇包括:100755,表示一個可執(zhí)行文件;120000表示一個符號鏈接。
現(xiàn)在可以通過write-tree命令將暫存區(qū)內(nèi)容寫入一個樹對象。無需指定-w 選項,如果某個樹對象不存在,調(diào)用write-tree命令時會根據(jù)當前暫存區(qū)狀態(tài)自動創(chuàng)建一個新的樹對象。
git write-tree
5bf35b145b6281c080d58b6d19a5113a47f782ed
git cat-file -p 5bf35b145b6281c080d58b6d19a5113a47f782ed
100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test
git cat-file -t 5bf35b145b6281c080d58b6d19a5113a47f782ed
tree
Git樹對象是在commit的過程中生成的,其生成會根據(jù).git目錄下的index文件的內(nèi)容來創(chuàng)建。git add的操作就是將文件的信息保存到index文件中,在commit時,根據(jù)index的內(nèi)容來生成樹對象。
使用git update-index可以為數(shù)據(jù)對象指定名稱和模式,然后使用git write-tree將樹對象寫入到Git文件系統(tǒng)中。
創(chuàng)建一個新的樹對象,包括test.txt文件的第二個版本以及一個新的文件。

echo 'new file' > new.txt
git update-index --cacheinfo 100644 \
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt

git update-index --add new.txt
暫存區(qū)現(xiàn)在包含test.txt文件的新版本和一個新文件new.txt,使用當前暫存區(qū)生成新的樹對象。
git write-tree
0155eb4229851634a0f03eb265b69f5a2d56f341
git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341

100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt

新的樹對象包含兩條文件記錄,同時test.txt的SHA-1值是第二版test.txt。 將第一個樹對象加入第二個樹對象,使其成為新的樹對象的一個子目錄。 通過調(diào)用read-tree命令可以把樹對象讀入暫存區(qū)。通過對 read-tree指定--prefix選項將一個已有的樹對象作為子樹讀入暫存區(qū)。

git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
git write-tree

3c4e9cd789d88d8d89c1073707c3585e41b0e614
git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614

040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt

如果基于新的樹對象創(chuàng)建一個工作目錄,工作目錄的根目錄包含兩個文件以及一個名為bak的子目錄,bak子目錄包含test.txt文件的第一個版本。
Git工程開發(fā)實踐(二)——Git內(nèi)部實現(xiàn)機制
樹對象解決了文件名的問題,而且由于分階段提交樹對象,樹對象可以看做是開發(fā)階段源代碼目錄樹的一次次快照,因此可以用樹對象作為源代碼版本管理。但需要記住每個樹對象的hash值,才能找到各階段的源代碼文件目錄樹。在源代碼版本控制中,還需要知道誰提交了代碼、什么時候提交的、提交的說明信息等,提交對象就是為了解決上述問題的。

4、Git提交對象

4.1Git提交對象簡介

提交對象指向一個樹對象,并且?guī)в邢嚓P的描述信息,標記項目某一個特定時間點的狀態(tài)。提交對象包含一些關于時間點的元數(shù)據(jù),如時間戳、最近一次提交的作者、指向上次提交的指針等等。
提交對象查看如下:
git show / git log + -s + --pretty=raw +對象名

4.2Git提交對象的生成

提交對象是用來保存提交的作者、時間、說明這些信息的,可以使用git commit-tree來將提交對象寫入到Git文件系統(tǒng)中。
echo 'first commit' | git commit-tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
162f9174ac6bb4c5d41bfc00fcb5147e2d62b839
commit-tree除了要指定提交的樹對象,也要提供提交說明,但提交的作者和時間則根據(jù)環(huán)境變量自動生成,并不需要指定。由于提交的作者和時間不同,提交對象的SHA-1哈希值也不相同。
提交對象的查看可以使用git cat-file。
git cat-file -p 162f9174ac6bb4c5d41bfc00fcb5147e2d62b839

tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author scorpio <642960662@qq.com> 1536497938 +0800
committer scorpio <642960662@qq.com> 1536497938 +0800

first commit

非首次提交需要指定使用-p指定父提交對象,使代碼版本才能成為一條時間線。
echo 'second commit' | git commit-tree 0155eb -p 162f9174ac6bb4c5d41bfc00fcb5147e2d62b839
f6bbc9d4e8de1b35ad66c2115aa8519587c26100
git cat-file查看一下新的提交對象,看到相比于第一次提交,多了parent部分。
第三次提交:
echo 'third commit' | git commit-tree 3c4e9c -p f6bbc9d4e8de1b35ad66c2115aa8519587c26100
第三次提交查看:
git log --stat 26a72965aa9c1bdab9fe5972012bd903f501f006 --pretty=oneline

26a72965aa9c1bdab9fe5972012bd903f501f006 third commit
 bak/test.txt | 1 +
 1 file changed, 1 insertion(+)
f6bbc9d4e8de1b35ad66c2115aa8519587c26100 second commit
 new.txt  | 1 +
 test.txt | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
162f9174ac6bb4c5d41bfc00fcb5147e2d62b839 first commit
 test.txt | 1 +
 1 file changed, 1 insertion(+)

最終提交對象的結構圖:
Git工程開發(fā)實踐(二)——Git內(nèi)部實現(xiàn)機制
合并的提交(merge commits)可能會有不只一個父對象。如果一個提交對象沒有父對象,稱為根提交(root commit),代表項目最初的一個版本(revision)。每個項目必須有至少有一個根提交(root commit)。

4.3Git提交對象的SHA-1哈希值計算

提交對象的內(nèi)容格式如下:

commit <content length><NUL>tree <tree sha>
parent <parent sha>
[parent <parent sha> if several parents from merges]
author <author name> <author e-mail> <timestamp> <timezone>
committer <author name> <author e-mail> <timestamp> <timezone>
<commit message>

第一次提交的提交對象的內(nèi)容如下:
git cat-file -p 162f9174ac6bb4c5d41bfc00fcb5147e2d62b839

tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author scorpio <642960662@qq.com> 1536497938 +0800
committer scorpio <642960662@qq.com> 1536497938 +0800

first commit

使用openssl計算SHA-1

echo -n "commit 165\0
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author scorpio <642960662@qq.com> 1536497938 +0800
committer scorpio <642960662@qq.com> 1536497938 +0800

first commit" | openssl sha1

5、Git對象存儲

Git中的數(shù)據(jù)對象解決了數(shù)據(jù)存儲的問題,樹對象解決了文件名存儲問題,提交對象解決了提交信息的存儲問題。
Git對象(數(shù)據(jù)對象、樹對象和提交對象)都存儲在.git/objects目錄下。
Git工程開發(fā)實踐(二)——Git內(nèi)部實現(xiàn)機制
Git對象的40位SHA-1哈希值分為兩部分:前兩位作為目錄名稱,后38位作為對象文件名。
Git對象的存儲路徑規(guī)則為:.git/objects/hash[0, 1]/hash[2, 40]
Git對象存儲的算法步驟:
A、計算content長度,構造header;
B、將header添加到content前面,構造Git對象;
C、使用sha1算法計算Git對象的40位hash碼;
D、使用zlib的deflate算法壓縮Git對象;
E、將壓縮后的Git對象存儲到.git/objects/hash[0, 2]/hash[2, 40]路徑下;
使用Nodejs來實現(xiàn)git hash-object -w的功能,即計算Git對象的hash值并存儲到Git文件系統(tǒng)中:

const fs = require('fs')
const crypto = require('crypto')
const zlib = require('zlib')
function gitHashObject(content, type) {
??// 構造header
??const header = `${type} ${Buffer.from(content).length}\0`
??// 構造Git對象
??const store = Buffer.concat([Buffer.from(header), Buffer.from(content)])
??// 計算hash
??const sha1 = crypto.createHash('sha1')
??sha1.update(store)
??const hash = sha1.digest('hex')
??// 壓縮Git對象
??const zlib_store = zlib.deflateSync(store)
??// 存儲Git對象
??fs.mkdirSync(`.git/objects/${hash.substring(0, 2)}`)
??fs.writeFileSync(`.git/objects/${hash.substring(0, 2)}/${hash.substring(2, 40)}`, zlib_store)
??console.log(hash)
}
// 調(diào)用入口
gitHashObject(process.argv[2], process.argv[3])

測試:
node index.js 'hello, world' blob
8c01d89ae06311834ee4b1fab2f0414d35f01102
git cat-file -p 8c01d89ae06311834ee4b1fab2f0414d35f01102
hello, world

三、Git引用

1、Git引用簡介

Git操作中經(jīng)常需要瀏覽完整的提交歷史,但為了能遍歷提交歷史從而找到所有相關對象,必須記住最后一個提交對象的SHA1哈希值。因此,需要一個文件來保存SHA-1值,并給文件起一個簡單名字,然后用名字來替代原始的 SHA-1值??梢栽?git/refs目錄下找到含有SHA-1值的文件。
find .git/refs

.git/refs
.git/refs/heads
.git/refs/tags

如果需要創(chuàng)建一個新引用來幫助記錄最新提交所在的位置,從技術上只需將最新提交對象的SHA1哈希值寫入引用文件內(nèi):

 echo "524fd8729bbee740392739d22f64784ec81a9804" > .git/refs/heads/test

然后就可以在Git命令中使用剛創(chuàng)建的新引用來代替SHA-1值。
git log --pretty=oneline test
通常,不提倡直接編輯引用文件。 如果想更新某個引用,Git提供了一個更加安全的命令update-ref來編輯引用。
Git分支的本質上是一個指向某一系列提交之首的指針或引用。 若想在某個提交對象上創(chuàng)建一個分支,可以進行如下操作:
git update-ref refs/heads/newbranchname commit_id

2、HEAD引用

當執(zhí)行git branch (branchname)時,Git通過HEAD文件獲取最新提交對象的SHA-值。HEAD文件是一個符號引用(symbolic reference),不像普通引用包含一個SHA-1值,而是一個指向其它引用的指針,指向當前所在的分支。 可以查看HEAD文件的內(nèi)容:
cat .git/HEAD
ref: refs/heads/master
如果執(zhí)行git checkout test,Git會對HEAD文件進行更新。
cat .git/HEAD
ref: refs/heads/test
當執(zhí)行git commit時,會創(chuàng)建一個提交對象,并用HEAD文件中引用所指向的SHA-1值設置其父提交字段。

3、標簽引用

標簽對象(tag object)類似于一個提交對象,包含一個標簽創(chuàng)建者信息、一個日期、一段注釋信息以及一個指針。主要的區(qū)別在于,標簽對象通常指向一個提交對象,而不是一個樹對象。 標簽對象永遠指向同一個提交對象,并給指向的提交對象加上一個更友好的名字。

4、遠程引用

如果添加了一個遠程版本庫并對其執(zhí)行過推送操作,Git會記錄下最近一次推送操作時每一個分支所對應的值,并保存在refs/remotes目錄下??梢蕴砑右粋€叫做origin的遠程版本庫,然后把master分支推送到遠程倉庫。
如果查看refs/remotes/origin/master文件,可以發(fā)現(xiàn)origin遠程版本庫的 master分支所對應的SHA-1值就是最近一次與服務器通信時本地master分支所對應的SHA-1值。
遠程引用和分支(位于refs/heads目錄下的引用)之間最主要的區(qū)別在于,遠程引用是只讀的。雖然可以git checkout 到某個遠程引用,但Git并不會將 HEAD引用指向該遠程引用。因此,永遠不能通過commit命令來更新遠程引用。 Git將遠程引用作為記錄遠程服務器上各分支最后已知位置狀態(tài)的書簽來管理。

四、Git包文件

Git最初向磁盤中存儲對象時所使用的格式被稱為“松散(loose)”對象格式。 但Git會時不時地將多個松散對象打包成一個稱為“包文件(packfile)”的二進制文件,以節(jié)省空間和提高效率。當版本庫中有太多的松散對象,或者手動執(zhí)行git gc命令,或者向遠程服務器執(zhí)行推送時,Git都會對對象打包。 要看到打包過程,可以手動執(zhí)行git gc命令讓Git對對象進行打包。
git gc

Counting objects: 47126, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (16945/16945), done.
Writing objects: 100% (47126/47126), done.
Total 47126 (delta 29923), reused 46986 (delta 29783)
向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI