Git資料存放區的原理淺析

來源:互聯網
上載者:User

寫作背景

進來在閑暇的時間裡在看一些關係P2P網路的拓撲發現的內容,重點關注了Markle Tree的知識點,在一篇文章裡(https://www.sdnlab.com/20095....),發現了了一句話 “Merkle DAG的一個常見例子就是Git存放庫”,於是尋找了一些關於git存放庫的原理,先整理如下。僅供自己和大家參考。

Git存放庫解析

當時我的疑問:

  • git怎麼儲存資料的,如何能根據儲存的資料可以很精確的回退到制定的版本?
  • git儲存和docker的儲存機制類似嗎?是不是都是分層的儲存?
  • git如果不是分層,每次提交都儲存起來,那麼資料量大了會怎麼辦?
解惑
我們的解惑路線是,從建立一個本地git倉庫開始,一步一步增加資料和提交,觀察內容的具體變化。
  • 首先使用git init建立一個本地倉庫,然後開啟倉庫中的.git檔案夾

    • HEAD表示當前提交的指標位置;
    • index是索引檔案;
    • refs檔案夾中的檔案是不同分支指向的commitID;
    • logs檔案夾中記錄的是每次refs的記錄;
    • objects檔案夾中的內容就是用來存放git本地倉庫對象
  • 既然找到了儲存git資料的位置,那麼git資料結構是什麼樣的呢?

    • git 是以索引值的方式儲存的,也就是說任何類型的資料都可以儲存。因此也可以在任何時候通過鍵取出對應的值;
    • git中底層產生了4中資料的對象:

      1. tree對象:可以看作一個目錄,管理一些“tree”對象或是“blob”對象。它有一串指向“blob”對象或是其它“tree”對象的指標,一般用來表示內容之間的目錄層次關係(就像檔案和子目錄)。
      2. blob對象: 一個“blob”通常用來隱藏檔的內容。一個“blob”對象就是一塊位元據,blob對象的鍵是根據SHA1演算法產生的,所以若兩個檔案在一個分類樹或是一個版本倉庫中有同樣的資料內容,那麼它們將會共用同一個“blob”對象,和其所對應的檔案所在路徑、檔案名稱是否改被更改都完全沒有關係。
      3. commit對象:“commit”對象指向一個“tree對象”,並且帶有相關的描述資訊,戳印金鑰目某一個特定時間點的狀態。它包括一些關於時間點的中繼資料,如時間戳記、最近一次提交的作者、指向上次提交的指標等等。
      4. tag對象: 一個“tag”對象包括一個對象名(SHA1簽名)、物件類型、標籤名、標籤建立人的名字(“tagger”), 還有一條可能包含有簽名(signature)的訊息。
  • 當新增一些內容的時候,進行git commit命令會出現什麼變化?

    • 當進行一次提交的時候,objects、logs和refs檔案夾都會發生變化,我們主要關注objects檔案夾。
    • 每次commit都會對資料進行一次儲存,會產生commit對象、tree對象和blob對象;
    • objects檔案夾裡面的資料存放的具體規則,對於這三種對象,都會用SHA-1對內容和頭資訊產生Hash值,去hash值的前兩位為objects目錄下面的檔案夾的名字,取剩餘38個字元為檔案名稱,例:8b0c4fe1567a463214c09334b54977e0114c90fe,取8b在objects建立一個檔案夾,取0c4fe1567a463214c09334b54977e0114c90fe為檔案名稱在8b檔案夾下建立一個檔案。
  • 知識點學習了之後,我們怎麼去驗證呢?

    • 使用 git cat-file 對我們提交的內容進行驗證。
    • 我進行了兩次commit,一次是完全建立的一個README.md檔案,裡面是有一行資料(### You Know);第二次commit,建立一個test.py檔案和在README.md中新添加了一些資料;
    • git cat-file -t查看對象的類型,git cat-file -p優雅的方式列印對象的內容。
  1. 使用git log --pretty=oneline查看我的兩次提交
  2. 使用git cat-file -t 172b54c8cd3eedca2fc301374286c2cb807d674f查看第一次提交的類型
  3. 使用git cat-file -p 172b54c8cd3eedca2fc301374286c2cb807d674fe查看第一次提交的內容
  4. 使用git cat-file -p 8b0c4fe1567a463214c09334b54977e0114c90fe查看第一次提交的tree對象,可以看到tree對象中存放的是一個blob對象,就是我們第一次提交建立的檔案README.md
  5. 使用git cat-file -p 67aeba604cea61ec63d19db0706b19d846c65ba4查看第一次提交的blob對象的內容為### You Know
  6. 使用git cat-file -p 03543a4c19023da01b5114d7f7a614d95a1bf084查看第二次提交的內容
  7. 使用git cat-file -p 03543a4c19023da01b5114d7f7a614d95a1bf084查看第二次提交的tree對象內容,包括修改的內容和新增的內容
  8. 使用git cat-file -p 03543a4c19023da01b5114d7f7a614d95a1bf084查看第二次提交的README.md blob對象內容,可以看到是整個檔案的全部內容,而不是僅僅包含修改的資料。
  • 總結問題的答案

    • git的資料存放區資料結構是索引值類型,分為4個對象,並且每次提交都是整個檔案的儲存,而不是分層的增加儲存,所以這樣會導致儲存的資料量很大,那git用的方法是使用zlib對資料進行壓縮,所以我們開啟儲存的檔案是這樣的資料,那我們都是用cat-file命令來查看的,怎麼才能這些內容是經過zlib壓縮過的呢?
    • 我用GO語言寫了一個簡單的程式,來驗證這些資料是經過zlib壓縮之後的,運行這個程式的時候帶上你要查看git對象的檔案路徑,就可以看到被還原的內容了;

GO代碼

package mainimport (    "bytes"    "compress/zlib"    "fmt"    "io"    "io/ioutil"    "os")//進行zlib壓縮func DoZlibCompress(src []byte) []byte {    var in bytes.Buffer    w := zlib.NewWriter(&in)    w.Write(src)    w.Close()    return in.Bytes()}//進行zlib解壓縮func DoZlibUnCompress(compressSrc []byte) []byte {    b := bytes.NewReader(compressSrc)    var out bytes.Buffer    r, _ := zlib.NewReader(b)    io.Copy(&out, r)    return out.Bytes()}func main() {    args := os.Args    if args == nil || len(args) < 2{        fmt.Println("Should input zlib file path.")       return     }               b, err := ioutil.ReadFile(args[1])    if err != nil {        fmt.Print(err)    }    fmt.Println(string(DoZlibUnCompress(b)))}

總結

  • 文章是參考了很多前輩部落格基礎上寫來的, 也有自己的實踐,所以很有必要記錄下來。
  • 有問題就想辦法去理解和解決,並通過動手實踐驗證。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.