git內(nèi)部原理讀書筆記

首先要弄明白一點(diǎn),從根本上來講 Git 是一個(gè)內(nèi)容尋址(content-addressable)文件系統(tǒng)斤程,并在此之上提供了一個(gè)版本控制系統(tǒng)的用戶界面。

1.低層命令(plumbing)和高層命令(porcelain)

高層命令:對(duì)用戶友好的一些命令包括我們常見的:push pull checkout branch等30多個(gè) 
參見:https://git-scm.com/book/zh/v2/Appendix-C%3A-Git-%E5%91%BD%E4%BB%A4-%E8%AE%BE%E7%BD%AE%E4%B8%8E%E9%85%8D%E7%BD%AE 附錄3

低層命令: cat-file ls-remote等命令

2.分析git目錄

首先初始化一個(gè)git文件 然后打開.git文件

hooks          
logs           
config         
objects        
ORIG_HEAD
description    
info           
refs           
HEAD           
FETCH_HEAD
packed-refs    
gc.log         
COMMIT_EDITMSG 
index

可以看到有這么多文件或文件夾
其中
description 文件僅供 GitWeb 程序使用菩混,我們無需關(guān)心
config 文件包含項(xiàng)目特有的配置選項(xiàng)忿墅。
info 目錄包含一個(gè)全局性排除(global exclude)文件,用以放置那些不希望被記錄在 .gitignore 文件中的忽略模式(ignored patterns)
hooks 目錄包含客戶端或服務(wù)端的鉤子腳本(hook scripts)

HEAD 文件  
(尚待創(chuàng)建的)index 文件  
objects 目錄  
refs 目錄

這4個(gè)目錄是最重要的是git的核心部分

  • objects 存放所有的數(shù)據(jù)內(nèi)容
  • refs 目錄存儲(chǔ)指向數(shù)據(jù)(分支)的提交對(duì)象的指針沮峡;
  • HEAD 文件指示目前被檢出的分支疚脐;
  • index 文件保存暫存區(qū)信息。

3.git對(duì)象

Git 是一個(gè)內(nèi)容尋址文件系統(tǒng).這意味著邢疙,Git 的核心部分是一個(gè)簡(jiǎn)單的鍵值對(duì)數(shù)據(jù)庫(key-value data store)棍弄。 你可以向該數(shù)據(jù)庫插入任意類型的內(nèi)容望薄,它會(huì)返回一個(gè)鍵值,通過該鍵值可以在任意時(shí)刻再次檢索(retrieve)該內(nèi)容照卦。

我們打開一個(gè)使用過git的.git/objects目錄
可以看到很多文件夾
每個(gè)文件夾中都有一個(gè)文件
比較特殊的有2個(gè)文件:info, pack 這兩個(gè)文件后續(xù)會(huì)解釋

首先我們查看git是如何存儲(chǔ)文件的

使用git hash-object -w --stdin
w表示存儲(chǔ) 不添加則僅生成
stdin如果不添加則需要在命令后接入要處理的內(nèi)容
命令輸出一個(gè)長(zhǎng)度為 40 個(gè)字符的校驗(yàn)和式矫。 
這是一個(gè) SHA-1 哈希值——一個(gè)將待存儲(chǔ)的數(shù)據(jù)外加一個(gè)頭部信息(header)一起做 SHA-1 校驗(yàn)運(yùn)算而得的校驗(yàn)和。
校驗(yàn)和的前兩個(gè)字符用于命名子目錄役耕,余下的 38 個(gè)字符則用作文件名采转。

現(xiàn)在我們知道可以用hash-object存儲(chǔ)

然后通過cat-file命令我們可以解析git 取回?cái)?shù)據(jù)

cat-file是一個(gè)非常重要的命令

cat-file鏈接

-p 可以將git內(nèi)容解析 為我們展示友好的輸出
-t 可以讓 Git 告訴我們其內(nèi)部存儲(chǔ)的任何對(duì)象類型,只要給定該對(duì)象的 SHA-1 值

git 樹對(duì)象

它能解決文件名保存的問題瞬痘,也允許我們將多個(gè)文件組織到一起故慈。 Git 以一種類似于 UNIX 文件系統(tǒng)的方式存儲(chǔ)內(nèi)容,但作了些許簡(jiǎn)化框全。 所有內(nèi)容均以樹對(duì)象和數(shù)據(jù)對(duì)象的形式存儲(chǔ)察绷,其中樹對(duì)象對(duì)應(yīng)了 UNIX 中的目錄項(xiàng),數(shù)據(jù)對(duì)象則大致上對(duì)應(yīng)了 inodes 或文件內(nèi)容津辩。 一個(gè)樹對(duì)象包含了一條或多條樹對(duì)象記錄(tree entry)拆撼,每條記錄含有一個(gè)指向數(shù)據(jù)對(duì)象或者子樹對(duì)象的 SHA-1 指針,以及相應(yīng)的模式喘沿、類型闸度、文件名信息。

例如我們分析下.git目錄

git cat-file -p master^{tree} // 將當(dāng)前的master以樹對(duì)象輸出
100644 blob eccc066d0fee656b1cd5b0a0918acc12a04e54ed    README.md
040000 tree d8286c0bdd97ecf334347e556082e410ee6d8a16    data

樹對(duì)象指向了一個(gè)readme和另一個(gè)樹對(duì)象

graph TD
master-->|tree|data
master-->|blob|README

我們繼續(xù)看

git cat-file -p d8286c0bdd97ecf334347e556082e410ee6d8a16
100644 blob 682b2728d73775036b0624f8d2d2422e14cd71de    secret

這樣就拿到了data里面存儲(chǔ)的git對(duì)象

graph TD
master-->|tree|data
master-->|blob|README
data-->|blob|secret
*這里我們看到了一些100644等數(shù)字蚜印,這個(gè)是文件類型*
下面是git數(shù)據(jù)對(duì)象的類型
100644:表明這是一個(gè)普通文件
100755:表示一個(gè)可執(zhí)行文件
120000:表示一個(gè)符號(hào)鏈接
以及我們見到過的
040000: tree類型

下面我們生成一個(gè)樹對(duì)象
通常git根據(jù)某一時(shí)刻的暫存區(qū)生成樹對(duì)象
首先生成暫存區(qū)并把文件加入

git update-index --add --cacheinfo 100644 <SHA1> text1
通過這個(gè)命令我們吧一個(gè)名為text1的普通文件加入了暫存區(qū)
--add是因?yàn)槲覀冎皼]有創(chuàng)建過暫存區(qū)
--cacheinfo 命令因?yàn)閷⒁砑拥奈募挥?Git 數(shù)據(jù)庫中莺禁,而不是位于當(dāng)前目錄下

現(xiàn)在可以通過write-tree命令將暫存區(qū)文件生成一個(gè)樹對(duì)象

提交對(duì)象

如果有多個(gè)樹對(duì)象,分別代表了我們想要跟蹤的不同項(xiàng)目快照窄赋。若想重用這些快照哟冬,你必須記住所有三個(gè) SHA-1 哈希值。 并且忆绰,你也完全不知道是誰保存了這些快照浩峡,在什么時(shí)刻保存的,以及為什么保存這些快照错敢。 而以上這些红符,正是提交對(duì)象(commit object)能為你保存的基本信息。

通過調(diào)用 commit-tree 命令創(chuàng)建一個(gè)提交對(duì)象伐债,為此需要指定一個(gè)樹對(duì)象的 SHA-1 值,以及該提交的父提交對(duì)象

$ echo 'first commit' | git commit-tree d8329f
fdf4fc3344e67ab068f836878b6c4951e3b15f3d

查看文件
$ git cat-file -p fdf4fc3
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700

first commit

提交對(duì)象的格式很簡(jiǎn)單:它先指定一個(gè)頂層樹對(duì)象致开,代表當(dāng)前項(xiàng)目快照峰锁;然后是作者/提交者信息(依據(jù)你的 user.name 和 user.email 配置來設(shè)定,外加一個(gè)時(shí)間戳)双戳;留空一行虹蒋,最后是提交注釋。

我們生成了第一個(gè)提交 fdf4fc3344e67ab068f836878b6c4951e3b15f3d
接著使用commit-tree 對(duì)象提交新的對(duì)象并將第一個(gè)提交作為父對(duì)象

echo 'second commit' | git commit-tree 0155eb -p fdf4fc3

例如0155eb 是新的暫存區(qū)引用 fdf4fc3是父提交 

這個(gè)時(shí)候我們使用git log的話就可以看到真正的提交記錄了
這個(gè)就是每次我們使用git add 和 git commit時(shí)git為我們做的事情

Git 所做的實(shí)質(zhì)工作——將被改寫的文件保存為數(shù)據(jù)對(duì)象,更新暫存區(qū)魄衅,記錄樹對(duì)象峭竣,最后創(chuàng)建一個(gè)指明了頂層樹對(duì)象和父提交的提交對(duì)象。 這三種主要的 Git 對(duì)象——數(shù)據(jù)對(duì)象晃虫、樹對(duì)象皆撩、提交對(duì)象——最初均以單獨(dú)文件的形式保存在 .git/objects 目錄下

git 如何存儲(chǔ)對(duì)象

前面提到git生成SHA-1后會(huì)將前2位作為文件夾名后38位為文件名存儲(chǔ)。
git通過zlib壓縮文件并存儲(chǔ)

4.git 引用

我們可以借助git log等命令來瀏覽完整的提交歷史哲银,但為了能遍歷那段歷史從而找到所有相關(guān)對(duì)象扛吞,你仍須記住 某個(gè)SHA-1 是最后一個(gè)提交。 我們需要一個(gè)文件來保存 SHA-1 值荆责,并給文件起一個(gè)簡(jiǎn)單的名字滥比,然后用這個(gè)名字指針來替代原始的 SHA-1 值。

git中這樣的文件稱為引用(references)存放在refs目錄下

我們可以通過update-ref來創(chuàng)建引用

git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
這個(gè)命令就是創(chuàng)建一個(gè)master的引用對(duì)象 指向1a這個(gè)提交對(duì)象

同時(shí)我們也可以創(chuàng)建別的引用對(duì)象

git update-ref refs/heads/xunlu 1a410efbd13591db07496601ebc7a059dd55cfe9

這個(gè)命令就相當(dāng)于在1a這個(gè)提交對(duì)象下git branch xunlu

那么git 如何知道當(dāng)前的分支呢
答案是HEAD文件
HEAD文件是一個(gè)符號(hào)引用指向目前所在的分支做院, 所謂符號(hào)引用盲泛,意味著它并不像普通引用那樣包含一個(gè) SHA-1 值——它是一個(gè)指向其他引用的指針

cat .git/HEAD
ref: refs/heads/master

當(dāng)我們執(zhí)行g(shù)it commit時(shí),git會(huì)創(chuàng)建一個(gè)提交對(duì)象键耕,并用 HEAD 文件中那個(gè)引用所指向的 SHA-1 值設(shè)置其父提交字段寺滚。

你可以通過symbolic-ref命令來查看或者修改HEAD文件

 git symbolic-ref HEAD refs/heads/test
 將HEAD指向test分支

還有標(biāo)簽引用和遠(yuǎn)程引用
標(biāo)簽引用就是創(chuàng)建了一個(gè)永遠(yuǎn)指向一個(gè)固定的提交對(duì)象的引用,相當(dāng)于起了別名
遠(yuǎn)程引用:如果你添加了一個(gè)遠(yuǎn)程版本庫并對(duì)其執(zhí)行過推送操作郁竟,Git 會(huì)記錄下最近一次推送操作時(shí)每一個(gè)分支所對(duì)應(yīng)的值玛迄,并保存在 refs/remotes 目錄下

5.包文件

git 使用zlib壓縮文件
當(dāng)你對(duì)同一個(gè)很大的文件修改哪怕一行以后你會(huì)發(fā)現(xiàn) git 會(huì)使用全新的文件存儲(chǔ)這個(gè)修改了的文件 放在了object中,這就造成了極大的浪費(fèi) 這兩個(gè)文件幾乎相同棚亩。

如果存放一個(gè)文件放他們相同的部分豈不是更好蓖议。

Git 最初向磁盤中存儲(chǔ)對(duì)象時(shí)所使用的格式被稱為“松散(loose)”對(duì)象格式。 但是讥蟆,Git 會(huì)時(shí)不時(shí)地將多個(gè)這些對(duì)象打包成一個(gè)稱為“包文件(packfile)”的二進(jìn)制文件勒虾,以節(jié)省空間和提高效率。 當(dāng)版本庫中有太多的松散對(duì)象瘸彤,或者你手動(dòng)執(zhí)行 git gc 命令修然,或者你向遠(yuǎn)程服務(wù)器執(zhí)行推送時(shí),Git 都會(huì)這樣做质况。

通過 git gc命令 git生成了pack/ 文件和索引文件

可以使用 git verify-pac 命令查看已打包的內(nèi)容

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愕宋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子结榄,更是在濱河造成了極大的恐慌中贝,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臼朗,死亡現(xiàn)場(chǎng)離奇詭異邻寿,居然都是意外死亡蝎土,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門绣否,熙熙樓的掌柜王于貴愁眉苦臉地迎上來誊涯,“玉大人,你說我怎么就攤上這事蒜撮”┕梗” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵淀弹,是天一觀的道長(zhǎng)丹壕。 經(jīng)常有香客問我,道長(zhǎng)薇溃,這世上最難降的妖魔是什么菌赖? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮沐序,結(jié)果婚禮上琉用,老公的妹妹穿的比我還像新娘。我一直安慰自己策幼,他們只是感情好邑时,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著特姐,像睡著了一般晶丘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唐含,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天浅浮,我揣著相機(jī)與錄音,去河邊找鬼捷枯。 笑死滚秩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淮捆。 我是一名探鬼主播郁油,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼攀痊!你這毒婦竟也來了桐腌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤苟径,失蹤者是張志新(化名)和其女友劉穎哩掺,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涩笤,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嚼吞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蹬碧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舱禽。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖恩沽,靈堂內(nèi)的尸體忽然破棺而出誊稚,到底是詐尸還是另有隱情,我是刑警寧澤罗心,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布里伯,位于F島的核電站,受9級(jí)特大地震影響渤闷,放射性物質(zhì)發(fā)生泄漏疾瓮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一飒箭、第九天 我趴在偏房一處隱蔽的房頂上張望狼电。 院中可真熱鬧,春花似錦弦蹂、人聲如沸肩碟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽削祈。三九已至,卻和暖如春脑漫,著一層夾襖步出監(jiān)牢的瞬間髓抑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國打工窿撬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留启昧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓劈伴,卻偏偏與公主長(zhǎng)得像密末,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子跛璧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Git 學(xué)習(xí)筆記 GitHub瀏覽器快捷鍵:t: 查找 先丟一堆圖严里。。就是這么任性 目錄Git對(duì)象說明 1.Git...
    歌白梨閱讀 955評(píng)論 0 1
  • Git是目前最流行的版本管理系統(tǒng)追城,也是最先進(jìn)的分布式版本控制系統(tǒng)(distributed version cont...
    pro648閱讀 5,698評(píng)論 1 17
  • 1.天魁星…呼保義…宋江 被賈忠刹碾、賈義兄弟所擒,押赴京城凌遲處死座柱。 2. 天罡星…玉麒麟…盧俊義 被二張擒住迷帜,押赴...
    荊大奇閱讀 4,470評(píng)論 0 1
  • 一戏锹、人品: 【真誠】 一個(gè)人如果活得真誠冠胯,就一定生活在一個(gè)遙遠(yuǎn)的國度〗跽耄——梭羅《瓦爾登湖》 我相信真誠的人是最好最...
    暖香盈袖閱讀 142評(píng)論 0 0
  • 91【工具】用好蘋果語音的三個(gè)小技巧 蘋果Siri 功能:句法荠察、設(shè)置、關(guān)鍵 問Siri 天氣奈搜,短信悉盆,打電話,帶我回...
    依盈閱讀 96評(píng)論 0 0