二就珠、Git內(nèi)部原理

1 前言

  • Git使用比較靈活,達(dá)到相同結(jié)果有多種方式醒颖。
  • 靠記憶不同場(chǎng)景下的命令組合妻怎,會(huì)停留在“知其然,不知其所以然”的層次泞歉。
  • 只有理解Git內(nèi)部原理和Git命令的底層操作逼侦,才能深入淺出的靈活運(yùn)用Git。

2 Git內(nèi)部原理

Git是由C語言開發(fā)的一套內(nèi)容尋址文件系統(tǒng)腰耙,并在此之上提供了一個(gè)VCS用戶界面榛丢。

2.1 Git目錄結(jié)構(gòu)

使用git init命令初始化當(dāng)前目錄,生成.git文件夾挺庞。

git init 初始化

  1. 工作區(qū)晰赞、暫存區(qū)和Git倉庫
    • 工作區(qū)是當(dāng)前目錄(除去.git/),所有的編輯操作都在該目錄進(jìn)行选侨。
    • 暫存區(qū)對(duì)應(yīng).git/index文件掖鱼,它包含了當(dāng)前暫存區(qū)的信息,由它可生成git的tree對(duì)象援制。(git init執(zhí)行后并沒有產(chǎn)生.git/index戏挡,而是在首次執(zhí)行git add命令后才生成,并把由更新文件生成的blob對(duì)象放入.git/objects/內(nèi)晨仑。)
      git add生成.git/index
    • git倉庫對(duì)應(yīng).git/褐墅,它存儲(chǔ)了項(xiàng)目的所有歷史快照拆檬,以供需要的時(shí)候使用。
  2. .git/目錄
    .git/包含了以下目錄和文件:
    • branches/:新版本不再使用
    • description:僅供GitWeb程序使用
    • config:當(dāng)前項(xiàng)目的配置選項(xiàng)
    • info/:不同于.gitignore文件掌栅,可配置本地的文件忽略模式,不會(huì)push到remote庫而影響其他人码泛。
    • hooks/:目錄存放鉤子腳本
    • objects/:目錄存儲(chǔ)所有數(shù)據(jù)內(nèi)容
    • refs/:目錄存儲(chǔ)指向數(shù)據(jù)的commit對(duì)象的指針
    • HEAD:文件內(nèi)容為當(dāng)前分支
    • index:文件內(nèi)容為暫存區(qū)的信息
2.2 Git命令

Git包含底層命令(Plumbing)和高層命令(Procelain)猾封。

  1. 用戶平時(shí)使用的Git命令一般為高層命令,如add噪珊、commit晌缘、checkout等;高層命令對(duì)用戶友好痢站,便于理解和操作磷箕。
  2. Git起初被設(shè)計(jì)為供VCS使用的工具集,這些工具也稱為底層命令阵难;底層命令一般不被用戶直接使用岳枷,而是被shell或腳本調(diào)用。
    Git部分底層命令

    此處列舉幾個(gè)底層命令簡(jiǎn)要說明:

    • checkout-index:Copy files from the index to the working tree.
    • cat-file:Provide content or type and size information for repository objects.
    • hash-object:Compute object ID and optionally creates a blob from a file.
    • update-index:Register file contents in the working tree to the index.
    • write-tree:Create a tree object from the current index.
    • commit-tree:Create a new commit object.
2.3 Git對(duì)象

Git定義了4種對(duì)象:blob呜叫、tree空繁、commit和tag,它們都位于.git/objects/目錄下朱庆。git對(duì)象在原文件的基礎(chǔ)上增加了一個(gè)頭部盛泡,即對(duì)象內(nèi)容 = 對(duì)象頭 + 文件內(nèi)容。這種格式無法直接通過cat命令讀取娱颊,需要使用git cat-file這個(gè)底層命令才能正確讀取傲诵。
對(duì)象頭的格式為:對(duì)象頭 = 對(duì)象類型 + 空格 + 數(shù)據(jù)內(nèi)容長度 + null byte,例如一個(gè)文件內(nèi)容為“hello world”箱硕,其blob對(duì)象頭為"blob 11\000"拴竹。

git cat-file可讀取git的4種對(duì)象

  • blob:工作區(qū)的文件以blob對(duì)象的形式進(jìn)入git倉庫,相當(dāng)于UNIX中的inodes或文件內(nèi)容剧罩。
  • tree:tree對(duì)象包含對(duì)blob對(duì)象以及其他tree對(duì)象的引用殖熟,相當(dāng)于UNIX中的目錄。
  • commit:包含了上一次commit對(duì)象的Hash串引用斑响、該時(shí)間點(diǎn)項(xiàng)目快照的頂層tree對(duì)象的Hash串引用菱属、作者/提交者信息、時(shí)間戳舰罚、空行纽门,以及提交的注釋信息。
    commit营罢、tree赏陵、blob的引用關(guān)系
  • tag:包含一個(gè)commit的Hash串引用饼齿、標(biāo)簽名,以及其他信息(由標(biāo)簽類型決定)蝙搔。
2.4 內(nèi)容尋址
  1. 依賴底層命令git hash-object命令缕溉,對(duì)文件內(nèi)容增加頭信息后計(jì)算hash值并返回,增加-w參數(shù)后在git倉庫內(nèi)創(chuàng)建blob對(duì)象(blob對(duì)象 = 對(duì)象頭 + 文件內(nèi)容)吃型。
  2. blob對(duì)象存儲(chǔ)到git倉庫目錄(.git/objects/)時(shí)证鸥,依據(jù)40位(16進(jìn)制字符)長度的hash串指定存儲(chǔ)目錄(hash串前2位)和命名文件(hash串后38位)。例如某blob對(duì)象的hash值為62/0d4582bfbf773ef15f9b52ac434906a3cdf9c3勤晚,那么它在git倉庫中的路徑為.git/objects/62/0d4582bfbf773ef15f9b52ac434906a3cdf9c3枉层。
  3. Git內(nèi)容尋址本質(zhì)是:Git根據(jù)由文件內(nèi)容(增加文件頭)產(chǎn)生的Hash值來標(biāo)識(shí)和索引文件,另外進(jìn)行命令操作時(shí)沒有必要寫完整的hash串赐写,只要輸入的hash串長度是唯一可識(shí)別和索引的即可鸟蜡。
    根據(jù)文件內(nèi)容的hash值索引文件
  4. 無需考慮Hash碰撞的情況,在大型項(xiàng)目上也可以放心使用Git挺邀。因?yàn)樵诟怕噬蟂HA-1產(chǎn)生的哈希值碰撞的機(jī)會(huì)可以小到忽略揉忘。
2.5 Git版本機(jī)制
  1. HEAD指向當(dāng)前分支。若master是當(dāng)前分支端铛,則HEAD文件內(nèi)容為ref: refs/heads/master癌淮。
    HEAD指向當(dāng)前分支
  2. 分支(本地分支、遠(yuǎn)程分支沦补、遠(yuǎn)程跟蹤分支汇荐、跟蹤分支)和標(biāo)簽(tag對(duì)象)都包含了對(duì)commit對(duì)象的引用但金。
    master分支引用了hash為1ad0的commit對(duì)象
  3. commit對(duì)象包含了上次commit對(duì)象的引用(類似單鏈表)和本次提交的頂級(jí)tree對(duì)象的引用晴及。
    commit對(duì)象引用了tree對(duì)象
    • 每個(gè)頂級(jí)tree對(duì)象可看做是一個(gè)完整的版本诊笤。
    • 通過commit對(duì)象的鏈?zhǔn)浇Y(jié)構(gòu)進(jìn)行串聯(lián),形成提交歷史和版本歷史产舞。
  4. 總之:git的分支和標(biāo)簽通過引用commit對(duì)象來標(biāo)注當(dāng)前分支的版本信息魂奥。
    git的版本歷史機(jī)制

    Note:凡是對(duì)Git對(duì)象的引用,都指的是Git對(duì)象的40位長度的Hash串易猫。

2.6 引用規(guī)格(refspec)

引用規(guī)格指的是遠(yuǎn)程倉庫分支和本地分支的映射耻煤,可表示為<src>:<dst>,這也暗示了數(shù)據(jù)流向?yàn)?code>src → dst准颓。

  1. fetch和push命令
# 兩命令都包含引用規(guī)格(refspec)來指定數(shù)據(jù)流向哈蝇。
git fetch [remote repository] [remote branch]:[local branch]
git push [remote repository] [local branch]:[remote branch]
  1. config文件配置refspec
    當(dāng)使用缺省的fetch/push命令時(shí),Git會(huì)根據(jù).git/config中的refspec配置進(jìn)行操作攘已。
  • 當(dāng)通過git remote add命令添加一個(gè)遠(yuǎn)程分支的同時(shí)炮赦,會(huì)在.git/config文件中添加一個(gè)配置結(jié)點(diǎn)。
    git remote add
    fetch中的”+“是可選的样勃,它告訴Git在不能fast-forward的情況下吠勘,也強(qiáng)制去更新它性芬。此后執(zhí)行git fetch orgin這個(gè)缺省命令時(shí),會(huì)拉取origin遠(yuǎn)程倉庫的所有分支剧防。
  • 可通過git log origin/master來查看從遠(yuǎn)程倉庫fetch的master分支植锉。
# 以下三個(gè)命令是等價(jià)的,Git會(huì)把他們都擴(kuò)展為refs/remote/origin/master
git log origin/master
git log remote/origin/master
git log refs/remote/origin/master
  • refspec指定分支映射
    1)可通過改寫fetch行為fetch = +refs/heads/master:refs/remotes/origin/mymaster峭拘,指定把遠(yuǎn)程的master分支映射為本地的origin/mymaster分支俊庇。
    2)也可指定多個(gè)映射,一次拉取多個(gè)指定分支棚唆。
[remote "origin"]
      url = git@github.com:kivihub/test.git
      fetch = +refs/heads/master:refs/remotes/origin/master
      fetch = +refs/heads/experiment:refs/remotes/origin/experiment
      fetch = +refs/heads/qa/*:refs/remote/orgin/qa/*

3)可同時(shí)指定push的refspec
若要把本地的master分支push到遠(yuǎn)程的qa/master分支暇赤,可配置如下:

[remote "origin"]
      url = git@github.com:kivihub/test.git
      fetch = +refs/heads/master:refs/remotes/origin/master
      fetch = +refs/heads/experiment:refs/remotes/origin/experiment
      fetch = +refs/heads/qa/*:refs/remote/orgin/qa/*
      push = refs/heads/master:refs/heads/qa/master 

4)刪除遠(yuǎn)程分支
通過命令git push origin :master可以刪除遠(yuǎn)程origin庫的master分支心例。因?yàn)閞efspec的格式為<src>:<dst>宵凌,通過把<src>置空表示把遠(yuǎn)程分支變?yōu)榭眨簿褪莿h除它止后。

2.7 其他
  1. git gc垃圾回收命令用于壓縮或刪除數(shù)據(jù)瞎惫,節(jié)省磁盤空間。
    • 將松散對(duì)象進(jìn)行打包存入packfile译株。
    • 將不被任何commit引用并且已存在一段時(shí)間(數(shù)月)的對(duì)象刪除瓜喇。
參考文章
  1. GIT科普系列5:index in git
  2. 《Pro Git》相關(guān)章節(jié)內(nèi)容
    2.1 Git 內(nèi)部原理 - 底層命令和高層命令
    2.2 Git 內(nèi)部原理 - Git 對(duì)象
    2.3 Git 內(nèi)部原理 - Git 引用
    2.4 Git 內(nèi)部原理 - 包文件
    2.5 Git 內(nèi)部原理 - 引用規(guī)格
    2.6 Git 內(nèi)部原理 - 傳輸協(xié)議
    2.7 Git 內(nèi)部原理 - 維護(hù)與數(shù)據(jù)恢復(fù)
    2.8 Git 內(nèi)部原理 - 環(huán)境變量
  3. Git命令列表
  4. .gitignore和exclude
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市歉糜,隨后出現(xiàn)的幾起案子乘寒,更是在濱河造成了極大的恐慌,老刑警劉巖匪补,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伞辛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡夯缺,警方通過查閱死者的電腦和手機(jī)蚤氏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踊兜,“玉大人竿滨,你說我怎么就攤上這事∧缶常” “怎么了于游?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長垫言。 經(jīng)常有香客問我曙砂,道長,這世上最難降的妖魔是什么骏掀? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任鸠澈,我火速辦了婚禮柱告,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笑陈。我一直安慰自己际度,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布涵妥。 她就那樣靜靜地躺著乖菱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蓬网。 梳的紋絲不亂的頭發(fā)上窒所,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音帆锋,去河邊找鬼吵取。 笑死,一個(gè)胖子當(dāng)著我的面吹牛锯厢,可吹牛的內(nèi)容都是我干的皮官。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼实辑,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼捺氢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剪撬,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤摄乒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后残黑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馍佑,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年萍摊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了挤茄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡冰木,死狀恐怖穷劈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情踊沸,我是刑警寧澤歇终,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站逼龟,受9級(jí)特大地震影響评凝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腺律,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一奕短、第九天 我趴在偏房一處隱蔽的房頂上張望宜肉。 院中可真熱鬧,春花似錦翎碑、人聲如沸谬返。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遣铝。三九已至,卻和暖如春莉擒,著一層夾襖步出監(jiān)牢的瞬間酿炸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國打工涨冀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留填硕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓蝇裤,卻偏偏與公主長得像廷支,于是被迫代替她去往敵國和親频鉴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子栓辜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

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

  • 謝謝一路有你陪伴
    WANCJF閱讀 166評(píng)論 0 0
  • 看 你看你交的都是什么朋友 手握一百種理由 / 也不愿向你低頭 看 你看你交的都是什么朋友 被人把心傷透 / 才回...
    efbec46c9d84閱讀 574評(píng)論 0 0
  • 在現(xiàn)實(shí)生活中,購物車是在超市垛孔、商店購物時(shí)存放商品的地方藕甩,而在網(wǎng)絡(luò)購物中,是對(duì)現(xiàn)實(shí)的購物車而喻周荐,買家可以像在超市里購...
    Crazy2015閱讀 5,741評(píng)論 0 3
  • Javascript是面向?qū)ο蟮恼Z言狭莱,所以在Javascript語言中,萬物皆是對(duì)象:字符串是對(duì)象概作、數(shù)字也是對(duì)象腋妙、...
    Melody_YM閱讀 264評(píng)論 0 0