<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一直用git,你了解git的內(nèi)部機(jī)制嗎?

          共 3293字,需瀏覽 7分鐘

           ·

          2021-01-04 17:09

          Python實(shí)戰(zhàn)社群

          Java實(shí)戰(zhàn)社群

          長(zhǎng)按識(shí)別下方二維碼,按需求添加

          掃碼關(guān)注添加客服

          進(jìn)Python社群▲

          掃碼關(guān)注添加客服

          進(jìn)Java社群


          作者丨Coder技術(shù)棧

          來(lái)源丨匠心Java


          ?大家好~我是Coder 老C,很高興又和大家見(jiàn)面了~


          在工作過(guò)程中我們會(huì)不可避免的使用Git,但是你知道Git是如何存儲(chǔ)你的文件、如何保存你的提交信息嗎?等等 了解這些也便于我們更好的理解和記憶命令,更好的排查問(wèn)題和使用Git,下面就讓我們來(lái)看一下吧~

          本文主要依照官網(wǎng)的介紹根據(jù)真實(shí)項(xiàng)目中的變化總結(jié)整理而成

          首先,我們要明確 Git 是一個(gè)分布式版本控制系統(tǒng) 其本質(zhì)是一套 內(nèi)容尋址文件系統(tǒng)

          通俗點(diǎn)說(shuō),Git 從核心上來(lái)看不過(guò)是簡(jiǎn)單地存儲(chǔ)鍵值對(duì)(key-value)。它允許插入任意類(lèi)型的內(nèi)容,并會(huì)返回一個(gè)鍵值,通過(guò)該鍵值可以在任何時(shí)候再取出該內(nèi)容。

          ps : 下面所說(shuō)的SHA-1碼 和 commit_id 是同一種


          首先,Git存儲(chǔ)在本地的表現(xiàn)形式

          當(dāng)你在一個(gè)新目錄或已有目錄內(nèi)執(zhí)行 git init 時(shí),Git 會(huì)創(chuàng)建一個(gè) .git 目錄,幾乎所有 Git 存儲(chǔ)和操作的內(nèi)容都位于該目錄下。如果你要備份或復(fù)制一個(gè)庫(kù),基本上將這一目錄拷貝至其他地方就可以了。如下圖:

          • info?目錄保存了一份不希望在 .gitignore 文件中管理的忽略模式 (ignored patterns) 的全局可執(zhí)行文件

          • hooks?目錄保存了客戶端或服務(wù)端鉤子腳本

          • config?文件包含了項(xiàng)目特有的配置選項(xiàng)

          • objects?目錄存儲(chǔ)所有數(shù)據(jù)內(nèi)容

          • refs?目錄存儲(chǔ)指向數(shù)據(jù) (分支) 的提交對(duì)象的指針

          • HEAD?文件指向當(dāng)前分支

          • index?文件保存了暫存區(qū)域信息

          其中,HEAD 及 index 文件,objects 及 refs 目錄是 Git 的核心部分。


          接下來(lái),說(shuō)一下Git的存儲(chǔ)方式

          如上述所說(shuō),objects 目錄存儲(chǔ)所有數(shù)據(jù)內(nèi)容,objects 目錄下的每一個(gè)文件是Git為每份存儲(chǔ)數(shù)據(jù)內(nèi)容生成一個(gè)文件,取得該內(nèi)容與頭信息的 SHA-1 校驗(yàn)和,創(chuàng)建以該校驗(yàn)和前兩個(gè)字符為名稱(chēng)的子目錄,并以 (校驗(yàn)和) 剩下 38 個(gè)字符為文件命名 (保存至子目錄下)。如下圖:打開(kāi)00文件夾可以看到里面保存的內(nèi)容:Git 以一種類(lèi)似 UNIX 文件系統(tǒng)但更簡(jiǎn)單的方式來(lái)存儲(chǔ)內(nèi)容。所有內(nèi)容以 tree 或 blob 對(duì)象存儲(chǔ),其中 tree 對(duì)象對(duì)應(yīng)于 UNIX 中的目錄,blob 對(duì)象則大致對(duì)應(yīng)于 inodes 或文件內(nèi)容。

          一個(gè)單獨(dú)的 tree 對(duì)象包含一條或多條 tree 記錄,每一條記錄含有一個(gè)指向 blob 或子 tree 對(duì)象的 SHA-1 指針,并附有該對(duì)象的權(quán)限模式 (mode)、類(lèi)型和文件名信息。

          正如 Git的每一次提交都是對(duì)代碼倉(cāng)庫(kù)的完整備份,也就是保存了一份代碼倉(cāng)庫(kù)完整的快照所說(shuō),每一個(gè)commit都是存儲(chǔ)為一個(gè)Tree,如下圖:具體在git中為:可以看到,目錄作為tree存儲(chǔ),文件作為blob存儲(chǔ)

          之后,我們通過(guò) git cat-file-p命令可以發(fā)現(xiàn)存儲(chǔ)是樹(shù)型的,也就是對(duì)應(yīng)于git的tree對(duì)象,保存的都是指向下一個(gè)部分的索引id 如下圖,每一步都是查看的上一步中的某個(gè)id:


          上述所說(shuō)每個(gè)commit創(chuàng)建一個(gè)樹(shù)快照,那么是通過(guò)什么創(chuàng)建的呢?

          這就是我們上述說(shuō)的 用于存儲(chǔ)暫存區(qū)信息的index文件了。

          通常 Git 根據(jù)你的暫存區(qū)域或 index 來(lái)創(chuàng)建并寫(xiě)入一個(gè) tree 。因此要?jiǎng)?chuàng)建一個(gè) tree 對(duì)象的話首先要通過(guò)將一些文件暫存從而創(chuàng)建一個(gè) index 。

          這也是為什么commit前必須要有文件被add到暫存區(qū),如果暫存區(qū)為空,commit會(huì)報(bào)錯(cuò)停止執(zhí)行。


          這個(gè)時(shí)候就有一個(gè)問(wèn)題了,我們有多個(gè)快照樹(shù),它們指向了你要跟蹤的項(xiàng)目的不同快照,其中也沒(méi)有關(guān)于誰(shuí)、何時(shí)以及為何保存了這些快照的信息

          此時(shí),commit對(duì)象就出場(chǎng)了~ 每次commit提交后就會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)commit 對(duì)象,這個(gè)對(duì)象就是為你保存了這些基本信息的。

          一般情況下,一次commit提交就可以理解為創(chuàng)建了一個(gè)tree樹(shù),以commit_id為根節(jié)點(diǎn)的tree,該樹(shù)包含了當(dāng)前項(xiàng)目的整體快照

          當(dāng)我們使用 git log命令查看提交歷史的時(shí)候,就展示了commit對(duì)象的一些基本信息,如下圖:

          其中:commit 后跟的id就是當(dāng)前commit快照的樹(shù)根節(jié)點(diǎn)id 其余的還包含作者,作者郵箱,創(chuàng)建時(shí)間等基本信息


          Git每次commit提交會(huì)保存項(xiàng)目快照,難道是將所有的文件重新復(fù)制一份嗎?

          當(dāng)然不可能,在git的文件系統(tǒng)中,是存在共用文件的。

          比如有三次commit提交,產(chǎn)生了三個(gè)tree樹(shù),它們?cè)谙蛳乱玫臅r(shí)候,如果兩個(gè)commit中的整個(gè)文件夾或者某個(gè)文件沒(méi)有改變,這兩個(gè)commit的tree會(huì)指向同一個(gè)對(duì)象。對(duì)于兩次提交修改了的文件,則會(huì)創(chuàng)建一個(gè)該文件的一個(gè)新的版本的文件,上一次提交指向舊的文件,修改文件的提交指向新版本的文件。

          整體情況如下圖:另外,Git 用 zlib 壓縮文件內(nèi)容,因此存儲(chǔ)的文件并不會(huì)占用太多空間


          了解了git整體存儲(chǔ)方式之后,我們?cè)倏匆幌虑懊嫣岬降拇鎯?chǔ)指向數(shù)據(jù) (分支) 的提交對(duì)象的指針的 refs目錄

          refs目錄內(nèi)容如下圖:首先,也是思考一個(gè)問(wèn)題:在項(xiàng)目開(kāi)發(fā)中,有許多分支,每個(gè)分支的提交記錄都不相同,我們也不可能去記住每個(gè)commit_id,去執(zhí)行像 git log1a410e 這樣的命令來(lái)查看完整的歷史,這樣的話你就要記得 1a410e 是你最后一次提交并且記得這個(gè)id,這樣才能在提交歷史中找到這些對(duì)象,git是怎樣的應(yīng)對(duì)這個(gè)問(wèn)題的呢?

          這時(shí)候,我們需要一個(gè)文件來(lái)用一個(gè)簡(jiǎn)單的名字來(lái)記錄這些 SHA-1 值,這樣就可以用這些指針而不是原來(lái)的 SHA-1 值去檢索了。在 Git 中,稱(chēng)之為“引用”(references 或者 refs)。

          可以在 .git/refs 目錄下面找到這些包含 SHA-1 值的文件。如下圖refs中heads文件下的文件,其中 每個(gè)文件存儲(chǔ)的是與文件名同名的分支的最新提交的commit_id添加上refs文件夾下的文件后,我們的Git存儲(chǔ)結(jié)構(gòu)就看起來(lái)像下圖:


          接下來(lái),再思考一個(gè)問(wèn)題,git是怎么標(biāo)識(shí)當(dāng)前是在什么分支,從而找到refs中對(duì)應(yīng)的映射文件獲取SHA-1值呢?

          那就是前面所說(shuō)的HEAD文件了,我們打開(kāi)文件可以看到以下內(nèi)容:ref:refs/heads/test_branch

          這里標(biāo)識(shí)的是當(dāng)前指向的是test_branch分支,并且指定了要是用的映射文件的路徑,這樣就解決了上述問(wèn)題,是不是特別簡(jiǎn)單~


          上述已經(jīng)介紹了Git的三個(gè)主要類(lèi)型:tree樹(shù)、commit對(duì)象、HEAD。下面我們說(shuō)一下Git中另外一個(gè)重要的東西:Tag(標(biāo)簽)Tag 對(duì)象比較簡(jiǎn)單,Tag對(duì)象非常像一個(gè) commit 對(duì)象---包含一個(gè)標(biāo)簽,一組數(shù)據(jù),一個(gè)消息和一個(gè)指針。最主要的區(qū)別就是 Tag 對(duì)象指向一個(gè) commit 而不是一個(gè) tree。它就像是一個(gè)分支引用,但是不會(huì)變化,永遠(yuǎn)指向同一個(gè) commit,僅僅是為了提供一個(gè)更加友好的名字。

          好了,通過(guò)介紹了git的核心組成元素 HEADindex文件,objectsrefs目錄 , 你應(yīng)該會(huì)對(duì)git的存儲(chǔ)和一些機(jī)制有一個(gè)簡(jiǎn)單的整體了解,這對(duì)我們更好的理解git命令和更好的使用git是有幫助的。希望本片文章會(huì)對(duì)大家有些許幫助~

          參考:git官網(wǎng)

          程序員專(zhuān)欄
          ?掃碼關(guān)注填加客服?
          長(zhǎng)按識(shí)別下方二維碼進(jìn)群

          近期精彩內(nèi)容推薦:??

          ?看電影前一定要檢查一下域名是不是HTTPS的

          ?有個(gè)大神級(jí)女朋友是什么體驗(yàn)

          ?世界上五個(gè)最不務(wù)正業(yè)的科學(xué)家!

          ?魂斗羅只有128KB為何可以實(shí)現(xiàn)那么長(zhǎng)的劇情





          在看點(diǎn)這里好文分享給更多人↓↓

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  视频无码在线 | 中国一级淫片 | 精品在线免费视频 | 亚洲高潮视频 | 午夜福利一区 |