日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

git存储原理

發(fā)布時間:2025/3/8 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 git存储原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

四種數(shù)據(jù)類型

實際上Git基于數(shù)據(jù)類型的不同,把對象分為四種:數(shù)據(jù)對象、樹對象、提交對象、標簽對象。Git文件系統(tǒng)的設計思路與linux文件系統(tǒng)相似,即將文件的內(nèi)容與文件的屬性分開存儲,文件內(nèi)容以“裝滿字節(jié)的袋子”存儲在文件系統(tǒng)中,文件名、所有者、權限等文件屬性信息則另外開辟區(qū)域進行存儲。在Git中,數(shù)據(jù)對象相當于文件內(nèi)容,樹對象相當于文件目錄樹,提交對象則是對文件系統(tǒng)的快照,標簽對象則是對提交信息的引用。

下面我們分別對每種對象進行說明(建議大家操作的時候觀察一下.git/objects目錄的變化)

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

數(shù)據(jù)對象是文件的內(nèi)容,不包括文件名、權限等信息。Git會根據(jù)文件內(nèi)容計算出一個hash值,以hash值作為文件索引存儲在Git文件系統(tǒng)中。由于相同的文件內(nèi)容的hash值是一樣的,因此Git將同樣內(nèi)容的文件只會存儲一次。git hash-object可以用來計算文件內(nèi)容的hash值,并將生成的數(shù)據(jù)對象存儲到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ù)對象寫入到Git文件系統(tǒng)中,如果不加這個選項,那么只計算文件的hash值而不寫入;–stdin表示從標準輸入中獲取文件內(nèi)容,當然也可以指定一個文件路徑代替此選項。上面講數(shù)據(jù)對象寫入到Git文件系統(tǒng)中,那如何讀取數(shù)據(jù)對象呢?git cat-file可以用來實現(xiàn)所有Git對象的讀取。

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

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

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

樹對象

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

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

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

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

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

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

提交對象

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

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

上面commit-tree除了要指定提交的樹對象,也要提供提交說明,至于提交的作者和時間,則是根據(jù)環(huán)境變量自動生成,并不需要指定。這里需要提醒一點的是,讀者在測試時,得到的提交對象hash值一般和這里不一樣,這是因為提交的作者和時間是因人而異的。此時相當于執(zhí)行了git commit

提交對象的查看,也是使用git cat-file:

$ git cat-file -p d555a9dfc304e74a9557a5d92dc0807c20765104 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 author defwang &lt;wangdefu@100tal.com&gt; 1607259906 +0800 committer defwang &lt;wangdefu@100tal.com&gt; 1607259906 +0800first commit$ git cat-file -t bb4de00acf2b259e767d8321e0fa3c865dae780e commit

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

$ git update-index --add --cacheinfo 100644 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test2.txt $ git write-tree e6cebf205657fb2046b5f38877bbfa8c3ae2d05c $ echo 'second commit' | git commit-tree e6cebf205657fb2046b5f38877bbfa8c3ae2d05c -p d555a9dfc304e74a9557a5d92dc0807c20765104 bb4de00acf2b259e767d8321e0fa3c865dae780e

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

$ git cat-file -p bb4de00acf2b259e767d8321e0fa3c865dae780e tree e6cebf205657fb2046b5f38877bbfa8c3ae2d05c parent d555a9dfc304e74a9557a5d92dc0807c20765104 author defwang &lt;wangdefu@100tal.com&gt; 1607260467 +0800 committer defwang &lt;wangdefu@100tal.com&gt; 1607260467 +0800second commit

使用git log可以查看整個提交歷史:

$ git log --stat bb4de00acf2b259e767d8321e0fa3c865dae780e commit bb4de00acf2b259e767d8321e0fa3c865dae780e Author: defwang &lt;wangdefu@100tal.com&gt; Date: Sun Dec 6 21:14:27 2020 +0800second committest2.txt | 1 +1 file changed, 1 insertion(+)commit d555a9dfc304e74a9557a5d92dc0807c20765104 Author: defwang &lt;wangdefu@100tal.com&gt; Date: Sun Dec 6 21:05:06 2020 +0800first committest.txt | 1 +1 file changed, 1 insertion(+)

有時候我們?yōu)榱朔奖阌洃浤骋淮翁峤?#xff0c;會對該提交打一個tag進行標記,這就產(chǎn)生了標簽對象

標簽對象

$ git tag -a v1.0.0 bb4de00acf2b259e767d8321e0fa3c865dae780e -m "test tag"

當執(zhí)行上面命令之后,.git目錄下的refs目錄中就會多一個文件

refs/tags└── v1.0.0

文件內(nèi)容為為40位的hash碼, 同樣我們使用git cat-file讀取該hash值

$ git cat-file -p 4599faa3ffb8042b85fce6f80cad2633b4ee01ff object bb4de00acf2b259e767d8321e0fa3c865dae780e type commit tag v1.0.0 tagger defwang &lt;wangdefu@100tal.com&gt; 1607262079 +0800test tag git cat-file -t 4599faa3ffb8042b85fce6f80cad2633b4ee01ff tag

可見該對象的類型為tag

至此,我們已經(jīng)知道了git的四種數(shù)據(jù)類型,blob、tree、commit、tag
Git中的數(shù)據(jù)對象解決了數(shù)據(jù)存儲的問題,樹對象解決了文件名存儲問題,提交對象解決了提交信息的存儲問題,標簽對象則是對提交對象進行更形象的命名,從Git設計中可以看出,Linus對一個源代碼版本控制系統(tǒng)做了很好的抽象和解耦,每種對象解決的問題都很明確,相比于使用一種數(shù)據(jù)結構,無疑更靈活和更易維護。

?

總結

以上是生活随笔為你收集整理的git存储原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。