1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        終于有人把 Git 的數(shù)據(jù)模型講清楚了!

        共 1142字,需瀏覽 3分鐘

         ·

        2021-11-27 00:23

        上一篇,我們講了 Git 的前世今生,神——Linus在 10 天內(nèi)就創(chuàng)造了 Git 的第一版,這一篇,我們來(lái)探究一下 Git 的數(shù)據(jù)模型。

        由于公眾號(hào)的文章發(fā)布后不能修改,也沒(méi)辦法加個(gè)統(tǒng)一的目錄作為索引頁(yè),所以二哥就把《Java 程序員進(jìn)階之路》的系列文章開(kāi)源到了 GitHub(點(diǎn)擊閱讀原文可以直接跳轉(zhuǎn)):

        https://github.com/itwanger/toBeBetterJavaer

        每天看著 star 數(shù)(目前已有 716 個(gè) star)的上漲我心里非常的開(kāi)心,希望越來(lái)越多的 Java 愛(ài)好者能因?yàn)檫@個(gè)開(kāi)源項(xiàng)目而受益,而越來(lái)越多人的 star,也會(huì)激勵(lì)我繼續(xù)更新下去~

        盡管 Git 的接口有些難懂,但它底層的設(shè)計(jì)和思想?yún)s非常的優(yōu)雅。難懂的接口只能靠死記硬背,但優(yōu)雅的底層設(shè)計(jì)則非常容易理解。我們可以通過(guò)一種自底向上的方式來(lái)學(xué)習(xí) Git,先了解底層的數(shù)據(jù)模型,再學(xué)習(xí)它的接口??梢赃@么說(shuō),一旦搞懂了 Git 的數(shù)據(jù)模型,再學(xué)習(xí)它的接口并理解這些接口是如何操作數(shù)據(jù)模型的就非常容易了。

        進(jìn)行版本控制的方法很多,Git 擁有一個(gè)精心設(shè)計(jì)的模型,這使其能夠支持版本控制所需的所有特性,比如維護(hù)歷史記錄、支持分支和團(tuán)隊(duì)協(xié)作。

        快照

        Git 將頂級(jí)目錄中的文件和文件夾稱(chēng)作集合,并通過(guò)一系列快照來(lái)管理歷史記錄。在 Git 的術(shù)語(yǔ)中,文件被稱(chēng)為 blob 對(duì)象(數(shù)據(jù)對(duì)象),也就是一組數(shù)據(jù)。目錄則被稱(chēng)為 tree(樹(shù)),目錄中可以包含文件和子目錄。

        ?(tree)
        |
        +-?foo?(tree)
        |??|
        |??+?bar.txt?(blob,?contents?=?"hello?world")
        |
        +-?baz.txt?(blob,?contents?=?"git?is?wonderful")

        頂層的樹(shù)(也就是 root) 包含了兩個(gè)元素,一個(gè)名為 foo 的子樹(shù)(包含了一個(gè) blob 對(duì)象“bar.txt”),和一個(gè) blob 對(duì)象“baz.txt”。

        歷史記錄建模:關(guān)聯(lián)快照

        版本控制系統(tǒng)是如何和快照進(jìn)行關(guān)聯(lián)的呢?線性歷史記錄是一種最簡(jiǎn)單的模型,它包含了一組按照時(shí)間順序線性排列的快照。不過(guò),出于種種原因,Git 沒(méi)有采用這種模型。

        在 Git 中,歷史記錄是一個(gè)由快照組成的有向無(wú)環(huán)圖?!坝邢驘o(wú)環(huán)圖”,聽(tīng)起來(lái)很高大上,但其實(shí)并不難理解。我們只需要知道這代表 Git 中的每個(gè)快照都有一系列的父輩,也就是之前的一系列快照。這些快照通常被稱(chēng)為“commit”,看起來(lái)好像是下面這樣:

        o?<--?o?<--?o?<--?o
        ????????????^??
        ?????????????\
        ??????????????---?o?<--?o

        o 表示一次 commit,也就是一次快照。箭頭指向了當(dāng)前 commit 的父輩。在第三次 commit 之后,歷史記錄分叉成了兩條獨(dú)立的分支,這可能是因?yàn)橐瑫r(shí)開(kāi)發(fā)兩個(gè)不同的特性,它們之間是相互獨(dú)立的。開(kāi)發(fā)完成后,這些分支可能會(huì)被合并為一個(gè)新的 commit,這個(gè)新的 commit 會(huì)同時(shí)包含這些特性,看起來(lái)好像是下面這樣:

        o?<--?o?<--?o?<--?o?<----?o
        ????????????^????????????/
        ?????????????\??????????v
        ??????????????---?o?<--?o

        Git 中的 commit 是不可改變的。當(dāng)然了,這并不意味著不能被修改,只不過(guò)這種“修改”實(shí)際上是創(chuàng)建了一個(gè)全新的提交記錄。

        數(shù)據(jù)模型及其偽代碼表示

        以偽代碼的形式來(lái)學(xué)習(xí) Git 的數(shù)據(jù)模型,可能更加通俗易懂。

        //?文件是一組數(shù)據(jù)
        type?blob?=?array

        //?一個(gè)包含了文件和子目錄的目錄
        type?tree?=?map

        //?每個(gè)?commit?都包含了一個(gè)父輩,元數(shù)據(jù)和頂層樹(shù)
        type?commit?=?struct?{
        ????parent:?array?//?父輩
        ????author:?string?//?作者
        ????message:?string?//?信息
        ????snapshot:?tree?//?快照
        }

        對(duì)象和內(nèi)存尋址

        Git 中的對(duì)象可以是 blob、tree 或者 commit:

        type?object?=?blob?|?tree?|?commit

        Git 在存儲(chǔ)數(shù)據(jù)的時(shí)候,所有的對(duì)象都會(huì)基于它們的安全散列算法進(jìn)行尋址。

        objects?=?map

        def?store(object):
        ????id?=?sha1(object)
        ????objects[id]?=?object

        def?load(id):
        ????return?objects[id]

        blob、tree 和 commit 一樣,都是對(duì)象。當(dāng)它們引用其他對(duì)象時(shí),并沒(méi)有真正在硬盤(pán)上保存這些對(duì)象,而是僅僅保存了它們的哈希值作為引用。

        還記得之前的例子嗎?

        ?(tree)
        |
        +-?foo?(tree)
        |??|
        |??+?bar.txt?(blob,?contents?=?"hello?world")
        |
        +-?baz.txt?(blob,?contents?=?"git?is?wonderful")

        root 引用的 foo 和 baz.txt 就像下面這樣:

        100644?blob?4448adbf7ecd394f42ae135bbeed9676e894af85????baz.txt
        040000?tree?c68d233a33c5c06e0340e4c224f0afca87c8ce87????foo

        引用

        所有的快照都可以通過(guò)它們的哈希值來(lái)標(biāo)記,但 40 位的十六進(jìn)制字符實(shí)在是太難記了,很不方便。針對(duì)這個(gè)問(wèn)題,Git 的解決辦法是給這些哈希值賦予一個(gè)可讀的名字,也就是引用(reference),引用是指向 commit 的指針,與對(duì)象不同,它是可變的,可以被更新,指向新的 commit。通常,master 引用通常會(huì)指向主分支的最新一次 commit。

        references?=?map

        def?update_reference(name,?id):
        ????references[name]?=?id

        def?read_reference(name):
        ????return?references[name]

        def?load_reference(name_or_id):
        ????if?name_or_id?in?references:
        ????????return?load(references[name_or_id])
        ????else:
        ????????return?load(name_or_id)

        這樣,Git 就可以使用“master”這樣容易被記住的名稱(chēng)來(lái)表示歷史記錄中特定的 commit,而不需要再使用一長(zhǎng)串的十六進(jìn)制字符了。

        在 Git 中,當(dāng)前的位置有一個(gè)特殊的索引,它就是“HEAD”。

        倉(cāng)庫(kù)

        我們可以粗略地給出 Git 倉(cāng)庫(kù)的定義了:對(duì)象 和 引用。

        在硬盤(pán)上,Git 僅存儲(chǔ)對(duì)象和引用,因?yàn)槠鋽?shù)據(jù)模型僅包含這些東西。所有的 git 命令都對(duì)應(yīng)著對(duì) commit 樹(shù)的操作。


        參考資料:https://missing-semester-cn.github.io/2020/version-control/

        這是《Java 程序員進(jìn)階之路》專(zhuān)欄的第 73 篇(記得點(diǎn)擊「閱讀原文」鏈接去點(diǎn)個(gè) star 哦)。該專(zhuān)欄風(fēng)趣幽默、通俗易懂,對(duì) Java 愛(ài)好者極度友好和舒適??,內(nèi)容包括但不限于 Java 基礎(chǔ)、Java 集合框架、Java IO、Java 并發(fā)編程、Java 虛擬機(jī)、Java 企業(yè)級(jí)開(kāi)發(fā)(SSM、Spring Boot)等核心知識(shí)點(diǎn)。

        點(diǎn)擊上方名片,發(fā)送消息「03」 就可以獲取最新版《Java 程序員進(jìn)階之路》PDF 版了,讓我們一起成為更好的 Java 工程師吧,沖!

        瀏覽 50
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操批视频在线观看 | 国产三级免费网站 | 女人脱了裤衩让男人捅视频 | 91麻豆精品国产理伦片在线观看 | 成年人电影久久 | 插插天天| 男性吹潮教程chinese视频 | 逼网址 | 啊灬嗯灬轻点啊灬好深啊灬岳 | 美女挤奶免费看网站 |