Git 數據是怎么存儲的


git 的數據存儲數據結構是鍵值類型,git中底層生成了4中數據的對象

  • commit:commit 對象指向一個 tree 對象,並且帶有相關的描述信息.
  • tree: 可以看作一個目錄
  • blob: 通常用來存儲文件的內容
  • tag:tag 對象包括一個對象名(SHA1簽名)、對象類型、標簽名、標簽創建人的名字(“tagger”), 還有一條可能包含有簽名(signature)的消息

上圖出自 sixgo-Git數據存儲的原理淺析

舉例提交

> git commit -m 'chore: LAO'
[master (root-commit) 4b9fc1a] chore: LAO
 2 files changed, 57 insertions(+)
 create mode 100644 index.html
 create mode 100644 test.js

> git log
commit 4b9fc1a52e74ed4e408c4994296a1f960533f48b (HEAD -> master)
Author: Ever-lose <ever-lose@foxmail.com>
Date:   Mon May 4 19:28:20 2020 +0800

    chore: LAO

使用 git cat-file

# 獲取此 commitid 的類型,是 commit
> git cat-file -t 4b9fc1a52e74ed4e408c4994296a1f960533f48b
commit

# 獲取 tree
> git cat-file -p 4b9fc1a52e74ed4e408c4994296a1f960533f48b
tree 5937ab7ef5b6aaf4aad3ad4b09bfef7b97ee6e39
author Ever-lose <ever-lose@foxmail.com> 1588591700 +0800
committer Ever-lose <ever-lose@foxmail.com> 1588591700 +0800

chore: LAO

# 獲取 blob
> git cat-file -p 5937ab7ef5b6aaf4aad3ad4b09bfef7b97ee6e39
100644 blob 0f7b3babfbcec4778ef50337115faf87e67fc682    index.html
100644 blob 39a772dd49196db8bfffb50a58bd10bac3dcb4ab    test.js

# 獲取 index.html 里的 blob 內容
> git cat-file -p 0f7b3babfbcec4778ef50337115faf87e67fc682
<!DOCTYPE html>
<html lang="en">
<head>
... 省略

由此可知 git 存儲是存儲一整個文件的。並且能注意到項目目錄的 .git\objects 下有個目錄叫 4b,里面有個叫 9fc1a52e74ed4e408c4994296a1f960533f48b 的文件,其實 4b 取自 commitId 里前兩個字符,而 9fc1a52e74ed4e408c4994296a1f960533f48b 自然就是 commitId 里剩余的 38 個字符了。文件是二進制的,打開也看不明白。

第二次提交,筆者就修改了 index.html 里的第一行

> git commit -m 'chore: 第二次提交'
[master bd07fbb] chore: 第二次提交
 1 file changed, 1 insertion(+)

# 查看這兩次提交
> git log --pretty=oneline
bd07fbb7f181f868191862e542da1636109e4e46 (HEAD -> master) chore: 第二次提交
4b9fc1a52e74ed4e408c4994296a1f960533f48b chore: LAO

# 獲取 tree,注意下面 parent 是第一個 commitId
> git cat-file -p bd07fbb7f181f868191862e542da1636109e4e46
tree 2df4d0cfd56341eeecb705a6c5c3eaebb66d4c63
parent 4b9fc1a52e74ed4e408c4994296a1f960533f48b
author Ever-lose <ever-lose@foxmail.com> 1588592528 +0800
committer Ever-lose <ever-lose@foxmail.com> 1588592528 +0800

chore: 第二次提交

# 獲取 blob
>  git cat-file -p 2df4d0cfd56341eeecb705a6c5c3eaebb66d4c63
100644 blob 114653874c6ed19c24c15f71532199aece94799d    index.html
100644 blob 39a772dd49196db8bfffb50a58bd10bac3dcb4ab    test.js

# 查看 index.html 的 blob 對象,下文的 <!-- 測試提交 --> 就是修改的內容
> git cat-file -p 114653874c6ed19c24c15f71532199aece94799d
<!-- 測試提交 -->
<!DOCTYPE html>
<html lang="en">

結論

git 的數據存儲數據結構是鍵值類型,git中底層生成了4中數據的對象。

每個 commit,git 都要存儲所有的文件內容,所以這樣會導致存儲的數據量很大。所以檢出時使用 git clone xxxrepo --depth 1 會有奇效。

因為數據量大,git 自然不會采用明文傳遞文件了,所以 blob 內容是采用 zlib 進行數據壓縮了的,只是我們用 git cat-file 看不出罷了。

參考

sixgo-Git數據存儲的原理淺析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM