中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Git 內(nèi)部原理之 Git 對(duì)象

2018-07-02    來源:importnew

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬Linux鏡像隨意使用

最近在讀《Pro Git》這本書,其中有一章講Git的內(nèi)部原理,寫得非常好,讀完之后對(duì)于Git的理解會(huì)提升到一個(gè)新的層次。今后,我會(huì)寫一系列的關(guān)于Git內(nèi)部原理的文章,以幫助讀者加深對(duì)Git的認(rèn)識(shí)。內(nèi)容主要參考《Pro Git》這本書,但不同的是,我會(huì)對(duì)內(nèi)容進(jìn)行重新組織,以使大家更容易理解。

這篇文章的主題的Git對(duì)象。

從根本上來講,Git是一個(gè)內(nèi)容尋址的文件系統(tǒng),其次才是一個(gè)版本控制系統(tǒng)。記住這點(diǎn),對(duì)于理解Git的內(nèi)部原理及其重要。所謂“內(nèi)容尋址的文件系統(tǒng)”,意思是根據(jù)文件內(nèi)容的hash碼來定位文件。這就意味著同樣內(nèi)容的文件,在這個(gè)文件系統(tǒng)中會(huì)指向同一個(gè)位置,不會(huì)重復(fù)存儲(chǔ)。

Git對(duì)象包含三種:數(shù)據(jù)對(duì)象、樹對(duì)象、提交對(duì)象。Git文件系統(tǒng)的設(shè)計(jì)思路與linux文件系統(tǒng)相似,即將文件的內(nèi)容與文件的屬性分開存儲(chǔ),文件內(nèi)容以“裝滿字節(jié)的袋子”存儲(chǔ)在文件系統(tǒng)中,文件名、所有者、權(quán)限等文件屬性信息則另外開辟區(qū)域進(jìn)行存儲(chǔ)。在Git中,數(shù)據(jù)對(duì)象相當(dāng)于文件內(nèi)容,樹對(duì)象相當(dāng)于文件目錄樹,提交對(duì)象則是對(duì)文件系統(tǒng)的快照。

下面的章節(jié),會(huì)分別對(duì)每種對(duì)象進(jìn)行說明。開始說明之前,先初始化一個(gè)Git文件系統(tǒng):

$ mkdir git-test
$ cd git-test
$ git init

接下來的操作都會(huì)在git-test這個(gè)目錄中進(jìn)行。

數(shù)據(jù)對(duì)象

數(shù)據(jù)對(duì)象是文件的內(nèi)容,不包括文件名、權(quán)限等信息。Git會(huì)根據(jù)文件內(nèi)容計(jì)算出一個(gè)hash值,以hash值作為文件索引存儲(chǔ)在Git文件系統(tǒng)中。由于相同的文件內(nèi)容的hash值是一樣的,因此Git將同樣內(nèi)容的文件只會(huì)存儲(chǔ)一次。git hash-object可以用來計(jì)算文件內(nèi)容的hash值,并將生成的數(shù)據(jù)對(duì)象存儲(chǔ)到Git文件系統(tǒng)中:

$ echo 'version 1' | git hash-object -w --stdin
83baae61804e65cc73a7201a7252750c76066a30
$ echo 'version 2' | git hash-object -w --stdin
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
$ echo 'new file' | git hash-object -w --stdin
fa49b077972391ad58037050f2a75f74e3671e92

上面示例中,-w表示將數(shù)據(jù)對(duì)象寫入到Git文件系統(tǒng)中,如果不加這個(gè)選項(xiàng),那么只計(jì)算文件的hash值而不寫入;--stdin表示從標(biāo)準(zhǔn)輸入中獲取文件內(nèi)容,當(dāng)然也可以指定一個(gè)文件路徑代替此選項(xiàng)。

上面講數(shù)據(jù)對(duì)象寫入到Git文件系統(tǒng)中,那如何讀取數(shù)據(jù)對(duì)象呢?git cat-file可以用來實(shí)現(xiàn)所有Git對(duì)象的讀取,包括數(shù)據(jù)對(duì)象、樹對(duì)象、提交對(duì)象的查看:

$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30
version 1
$ git cat-file -t 83baae61804e65cc73a7201a7252750c76066a30
blob

上面示例中,-p表示查看Git對(duì)象的內(nèi)容,-t表示查看Git對(duì)象的類型。

通過這一節(jié),我們能夠?qū)it文件系統(tǒng)中的數(shù)據(jù)對(duì)象進(jìn)行讀寫。但是,我們需要記住每一個(gè)數(shù)據(jù)對(duì)象的hash值,才能訪問到Git文件系統(tǒng)中的任意數(shù)據(jù)對(duì)象,這顯然是不現(xiàn)實(shí)的。數(shù)據(jù)對(duì)象只是解決了文件內(nèi)容存儲(chǔ)的問題,而文件名的存儲(chǔ)則需要通過下一節(jié)的樹對(duì)象來解決。

樹對(duì)象

樹對(duì)象是文件目錄樹,記錄了文件獲取目錄的名稱、類型、模式信息。使用git update-index可以為數(shù)據(jù)對(duì)象指定名稱和模式,然后使用git write-tree將樹對(duì)象寫入到Git文件系統(tǒng)中:

$ git update-index --add --cacheinfo 100644 83baae61804e65cc73a7201a7252750c76066a30 test.txt
$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579

--add表示新增文件名,如果第一次添加某一文件名,必須使用此選項(xiàng);--cacheinfo <mode> <object> <path>是要添加的數(shù)據(jù)對(duì)象的模式、hash值和路徑,<path>意味著為數(shù)據(jù)對(duì)象不僅可以指定單純的文件名,也可以使用路徑。另外要注意的是,使用git update-index添加完文件后,一定要使用git write-tree寫入到Git文件系統(tǒng)中,否則只會(huì)存在于index區(qū)域。

樹對(duì)象仍然可以使用git cat-file查看:

$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30  test.txt
$ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
tree

上面表示這個(gè)樹對(duì)象只有test.txt這個(gè)文件,接下來我們將version 2的數(shù)據(jù)對(duì)象指定為test.txt,并添加一個(gè)新文件new.txt

$ git update-index --cacheinfo 100644 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
$ git update-index --add --cacheinfo 100644 fa49b077972391ad58037050f2a75f74e3671e92 new.txt
$ git write-tree
0155eb4229851634a0f03eb265b69f5a2d56f341

查看樹對(duì)象0155eb,可以發(fā)現(xiàn)這個(gè)樹對(duì)象有兩個(gè)文件了:

$ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341
100644 blob fa49b077972391ad58037050f2a75f74e3671e92  new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a  test.txt

我們甚至可以使用git read-tree,將已添加的樹對(duì)象讀取出來,作為當(dāng)前樹的子樹:

$ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git write-tree
3c4e9cd789d88d8d89c1073707c3585e41b0e614

--prefix表示把子樹對(duì)象放到哪個(gè)目錄下。查看樹對(duì)象,可以發(fā)現(xiàn)當(dāng)前樹對(duì)象有一個(gè)文件夾和兩個(gè)文件:

$ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614
040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579  bak
100644 blob fa49b077972391ad58037050f2a75f74e3671e92  new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a  test.txt

最終,整個(gè)樹對(duì)象的結(jié)構(gòu)如下圖:

樹對(duì)象結(jié)構(gòu)圖

樹對(duì)象解決了文件名的問題,而且,由于我們是分階段提交樹對(duì)象的,樹對(duì)象可以看做是開發(fā)階段源代碼目錄樹的一次次快照,因此我們可以是用樹對(duì)象作為源代碼版本管理。但是,這里仍然有問題需要解決,即我們需要記住每個(gè)樹對(duì)象的hash值,才能找到個(gè)階段的源代碼文件目錄樹。在源代碼版本控制中,我們還需要知道誰提交了代碼、什么時(shí)候提交的、提交的說明信息等,接下來的提交對(duì)象就是為了解決這個(gè)問題的。

提交對(duì)象

提交對(duì)象是用來保存提交的作者、時(shí)間、說明這些信息的,可以使用git commit-tree來將提交對(duì)象寫入到Git文件系統(tǒng)中:

$ echo 'first commit' | git commit-tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
db1d6f137952f2b24e3c85724ebd7528587a067a

上面commit-tree除了要指定提交的樹對(duì)象,也要提供提交說明,至于提交的作者和時(shí)間,則是根據(jù)環(huán)境變量自動(dòng)生成,并不需要指定。這里需要提醒一點(diǎn)的是,讀者在測(cè)試時(shí),得到的提交對(duì)象hash值一般和這里不一樣,這是因?yàn)樘峤坏淖髡吆蜁r(shí)間是因人而異的。

提交對(duì)象的查看,也是使用git cat-file

$ git cat-file -p db1d6f137952f2b24e3c85724ebd7528587a067a
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author jingsam <jing-sam@qq.com> 1528022503 +0800
committer jingsam <jing-sam@qq.com> 1528022503 +0800
first commit

上面是屬于首次提交,那么接下來的提交還需要指定使用-p指定父提交對(duì)象,這樣代碼版本才能成為一條時(shí)間線:

$ echo 'second commit' | git commit-tree 0155eb4229851634a0f03eb265b69f5a2d56f341 -p db1d6f137952f2b24e3c85724ebd7528587a067a
d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c

使用git cat-file查看一下新的提交對(duì)象,可以看到相比于第一次提交,多了parent部分:

$ git cat-file -p d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c
tree 0155eb4229851634a0f03eb265b69f5a2d56f341
parent db1d6f137952f2b24e3c85724ebd7528587a067a
author jingsam <jing-sam@qq.com> 1528022722 +0800
committer jingsam <jing-sam@qq.com> 1528022722 +0800
second commit

最后,我們?cè)賹鋵?duì)象3c4e9c提交:

$ echo 'third commit' | git commit-tree 3c4e9cd789d88d8d89c1073707c3585e41b0e614 -p d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c
3ac728ac62f0a7b5ac201fd3ed1f69165df8be31

使用git log可以查看整個(gè)提交歷史:

-
 2 files changed, 2 insertions(+), 1 deletion(-)
commit db1d6f137952f2b24e3c85724ebd7528587a067a
Author: jingsam <jing-sam@qq.com>
Date:   Sun Jun 3 18:41:43 2018 +0800
    first commit
 test.txt | 1 +
 1 file changed, 1 insertion(+)

最終的提交對(duì)象的結(jié)構(gòu)如下圖:

提交對(duì)象結(jié)構(gòu)示意圖

總結(jié)

Git中的數(shù)據(jù)對(duì)象解決了數(shù)據(jù)存儲(chǔ)的問題,樹對(duì)象解決了文件名存儲(chǔ)問題,提交對(duì)象解決了提交信息的存儲(chǔ)問題。從Git設(shè)計(jì)中可以看出,Linus對(duì)一個(gè)源代碼版本控制系統(tǒng)做了很好的抽象和解耦,每種對(duì)象解決的問題都很明確,相比于使用一種數(shù)據(jù)結(jié)構(gòu),無疑更靈活和更易維護(hù)。每種Git對(duì)象都有一個(gè)hash值,這個(gè)值是怎么計(jì)算出來的?Git的各種對(duì)象是如何存儲(chǔ)的?這些問題將在下一篇文章中講解。

標(biāo)簽: linux 代碼 權(quán)限

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:使用 lynis 進(jìn)行 linux 漏洞掃描

下一篇:JVM堆內(nèi)存使用率持續(xù)上升的一種排查思路