git存儲原理

四種數據類型

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

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

數據對象

數據對象是文件的內容,不包括文件名、權限等信息。Git會根據文件內容計算出一個hash值,以hash值作為文件索引存儲在Git文件系統中。由于相同的文件內容的hash值是一樣的,因此Git將同樣內容的文件只會存儲一次。git hash-object可以用來計算文件內容的hash值,并將生成的數據對象存儲到Git文件系統中:

$ 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表示將數據對象寫入到Git文件系統中,如果不加這個選項,那么只計算文件的hash值而不寫入;–stdin表示從標準輸入中獲取文件內容,當然也可以指定一個文件路徑代替此選項。上面講數據對象寫入到Git文件系統中,那如何讀取數據對象呢?git cat-file可以用來實現所有Git對象的讀取。

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

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

我們能夠對Git文件系統中的數據對象進行讀寫。但是,我們需要記住每一個數據對象的hash值,才能訪問到Git文件系統中的任意數據對象,這顯然是不現實的。數據對象只是解決了文件內容存儲的問題,而文件名的存儲則需要通過樹對象來解決。

樹對象

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

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

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

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

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

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

提交對象

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

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

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

有時候我們為了方便記憶某一次提交,會對該提交打一個tag進行標記,這就產生了標簽對象

標簽對象

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

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

refs/tags└── v1.0.0

文件內容為為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

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

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535422.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535422.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535422.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

詳解設計模式:中介者模式

中介者模式&#xff08;Mediator Pattern&#xff09;也被稱為調停者模式&#xff0c;是在 GoF 23 種設計模式中定義了的行為型模式。 中介者模式 是用來降低多個對象和類之間的通信復雜性。這種模式提供了一個中介類&#xff0c;該類通常處理不同類之間的通信&#xff0c;并支…

rebase參數以及注意事項

可以根據需要將pick參數&#xff0c;改變為下面代表不同作用的參數&#xff1b;這樣就可以對節點C和D進行不同的操作了。比如&#xff1a; pick&#xff1a;默認參數&#xff0c;表示不對提交節點進行任何操作&#xff0c;直接應用原提交節點。不創建新提交&#xff1b; rewor…

RPC 服務 與 HTTP 服務的區別

1、什么是RPC RPC&#xff08;Remote Procedure Call&#xff09;—遠程過程調用&#xff0c;它是一種通過網絡從遠程計算機程序上請求服務&#xff0c;而不需要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在&#xff0c;如TCP或UDP&#xff0c;為通信程序之間攜帶信…

Docker 網絡命名空間

Docker 用戶可以通過與 CNM 的 Object 以及 API 的交互來管理對應容器的網絡&#xff0c;下面是一個典型的容器網絡生命周期&#xff1a; 1、Driver要向NetworkController注冊。內置的Driver在Libnetwork內注冊&#xff0c;遠程的Driver則通過Plugin mechanism注冊。每一個Driv…

緩存雪崩、擊穿、穿透解決方案

用戶的數據一般都是存儲于數據庫&#xff0c;數據庫的數據是落在磁盤上的&#xff0c;磁盤的讀寫速度可以說是計算機里最慢的硬件了。 當用戶的請求&#xff0c;都訪問數據庫的話&#xff0c;請求數量一上來&#xff0c;數據庫很容易就奔潰的了&#xff0c;所以為了避免用戶直…

Ansible中的playbook詳解

首先簡單說明一下playbook&#xff0c;playbook是什么呢&#xff1f; 根本上說playbook和shell腳本沒有任何的區別&#xff0c;playbook就像shell一樣&#xff0c;也是把一堆的命令組合起來&#xff0c;然后加入對應條件判斷等等&#xff0c;在shell腳本中是一條一條的命令&am…

【Docker】容器鏡像有哪些特性

首先解釋一下什么是Docker鏡像&#xff1f; Docker鏡像它其實是一個模板&#xff0c;擁有這個模板我們才能創建我們的Docker容器&#xff0c;鏡像里含有啟動 docker 容器所需的文件系統結構及其內容&#xff0c;因此是啟動一個 docker 容器的基礎。docker 鏡像的文件內容以及一…

nginx中的location指令

1、location 介紹 location是Nginx中的塊級指令(block directive)&#xff0c;location指令的功能是用來匹配不同的url請求&#xff0c;進而對請求做不同的處理和響應&#xff0c;這其中較難理解的是多個location的匹配順序&#xff0c;本文會作為重點來解釋和說明。 開始之前…

容器底層實現技術Namespace/Cgroup

Docker容器實現原理 Docker容器在實現上是通過namespace技術來進行進程隔離&#xff0c;通過cgroup技術實現容器進程可用資源的限制&#xff0c;當docker啟動一個容器時&#xff0c;實際是創建了多了namespace參數的進程。 Namespace Namespace&#xff1a;命名空間 作用&#…

身體原因 斷更一周

由于眾所周知的原因&#xff0c;博主最近具有發熱、全身乏力、酸痛、干咳等癥狀&#xff0c;已嚴重影響日常的工作學習和博客編寫&#xff0c;所以斷更我將一周&#xff0c;由下周三&#xff08;即2022年12月21日&#xff09;恢復更新 更多往期內容可以參考&#xff1a;全網最…

異方差與多重共線性對回歸問題的影響

異方差的檢驗 1.異方差的畫圖觀察 2.異方差的假設檢驗&#xff0c;假設檢驗有兩種&#xff0c;一般用懷特檢驗使用方法在ppt中&#xff0c;課程中也有實驗&#xff0c;是一段代碼。 異方差的解決辦法 多重共線性 多重共線性可能帶來的影響&#xff1a; 多重共線性的檢驗 多重…

如何修改Docker的鏡像源

改或新增/etc/docker/daemon.json 文件 vi/etc/docker/daemon.json 添加需要修改的國內鏡像源鏡像源 { "registry-mirrors":["http://hub-mirror.c.163.com"] } 重啟Docker服務 Systemctl restart docker.service 方法二 修改或新增 /etc/sysconfig…

nginx 的 rewrite 模塊

ngxhttprewrite_module 模塊用來使用正則表達式&#xff08;PCRE&#xff09;改變請求的 URI&#xff0c;返回重定向&#xff0c;并有條件地選擇配置。 指令執行順序 首先順序執行 server 塊中的 rewrite 模塊指令&#xff0c;得到 rewrite 后的請求 URI 然后循環執行如下指令…

所有的Python庫

庫名稱簡介 Chardet字符編碼探測器&#xff0c;可以自動檢測文本、網頁、xml的編碼。 colorama主要用來給文本添加各種顏色&#xff0c;并且非常簡單易用。 Prettytable主要用于在終端或瀏覽器端構建格式化的輸出。 difflib&#xff0c;[Python]標準庫&#xff0c;計算文本…

Oracle行轉列語法總結大全

一、decode語法 SELECT deptno, nvl(SUM(decode(job, MANAGER, sal)), 0) s_MANAGER, nvl(SUM(decode(job, ANALYST, sal)), 0) s_ANALYST, nvl(SUM(decode(job, CLERK, sal)), 0) s_CLERK, nvl(SUM(decode(job, PRESIDENT, sal)), 0) s_PRESIDENT, …

Shell 各種符號 之 含義

#!&#xff1a;符號能夠被內核識別成是一個腳本的開始&#xff0c;這一行必須位于腳本的首行 $0&#xff1a;當前腳本的名字 $#&#xff1a;輸入<調用>參數(腳本或函數的位置參數) 的個數&#xff0c;如 NumArg$#&#xff1b;echo"\$#: $#;\$NumArg: $NumArg"…

Nginx的11個執行流程

1 Nginx簡介 Web服務器市場份額 Nginx [engine x] 最初由 Lgor Sysoev 編寫。根據 Netcraft 的數據&#xff0c;到2020年9月&#xff0c;Nginx 服務或代理了25.76&#xff05;站點&#xff0c;市場份額占到了約34.03&#xff05;。 Nginx 被廣泛用作&#xff1a; HTTP服務器…

Nginx的執行階段詳解

在了解nginx的執行階段前&#xff0c;先看一個例子 對echo不熟悉的&#xff0c;可以先看文章Nginx調試必備了解下echo擴展 回到上面這個例子&#xff0c;在server塊中配置這樣的location&#xff0c;你覺得輸出是什么樣子&#xff1f; 按照正常的邏輯&#xff0c;輸出應該是32 …

Docker掛了,數據如何找回

docker在實際使用中&#xff0c;讓運維人員詬病的&#xff0c;除了安全問題外&#xff0c;大概就是數據的問題了 很多人在初用docker的時候&#xff0c;很多時候都忘記或不知道docker中需要保留的數據需要掛載到宿主機文件夾到容器內部對應目錄&#xff08;當然除了掛載宿主機目…

TCP總結

TCP這些東西&#xff0c;基本每個程序猿都或多或少是掌握的了。雖然感覺在實際開發中沒有什么用武之處&#xff0c;但&#xff0c;面試他要問啊 而最近大家伙過完年&#xff0c;也都在準備春招&#xff0c;我也一樣。閱讀了一些okHttp源碼之后&#xff0c;又屁顛屁顛地跑回來重…