深刻理解Git - Git底層對象

前篇:
深刻理解Git - 一切皆commithtml

如何從稍微底層一點的角度,從底層實現理解一切皆commit ?git

配合希沃白板課件食用,效果更佳:
【希沃白板5】課件分享 : 《Git 進階 - 從使用角度深刻理解Git》
https://r302.cc/ke8XdO?platform=enpc&channel=copylink
點擊連接直接預覽課件3d

git 文件系統

git 本質上是一個基於鍵值對的文件系統。
文件系統,最重要的兩個內容,固然就是 文件 和 文件夾 了。code

blob object(數據對象)

git 中的 blob object 就是文件系統中的文件,包含 鍵:一個 hash 值和校驗值的組合,值:文件內容。orm

比較特殊的是:blob object 只存內容,不存文件名,文件名在 tree object 中保存。htm

tree object (樹對象)

至關於文件系統中的文件夾。對象

commit object(提交對象)

提交對象能夠理解爲對樹對象的一層封裝,裏面包含了提交時間,提交做者等信息,更重要的,裏面包含了父提交的ID,由此就能夠造成 git 提交的有向無環圖。blog


git 的這些對象的數據,保存在 .git/objects 目錄下。three

這裏,咱們並無發現分支這些概念,回顧以前說的『一切皆 commit』的理解,分支這些,不過是某個 commit 的引用。(都是紙老虎)圖片

案例

將 t/bugfix 分支重置到 a1b2c3 提交。

可使用熟悉的 reset 命令: (@t/bugfix)git reset --hard a1b2c3,也能夠用更底層的命令:git update-ref refs/head/t/bugfix a1b2c3

效果是同樣的,固然,平時使用,只推薦前者,這裏只是做爲對「分支是某個commit的引用」這句話理解的一個案例。

標籤對象

tag object(標籤對象)

標籤對象:指向一個特定對象的固定引用對象;
能夠給 git 中的任意對象打標籤;

標籤對象不是引用(與分支名不一樣),是一種獨立的git對象。但在使用上(針對提交的tag),體驗一致。因此「一切皆commit」這句話,對標籤而言,是不必定正確的,但實際使用中,通常只會給提交打標籤。


全部的引用,都記錄在 .git\refs 文件夾中。

壓縮與增量存儲

在沒有壓縮時,稱 git 的存儲模式爲鬆散的對象模式,即一個文件的不一樣版本,都是保存其所有的數據。在 git gc 時,會壓縮並實現增量存儲。這個命令在執行 pull 等命令時自動觸發。

爲何 git 完全刪除大文件要修改整個歷史?

由於提交的不可變性,如圖,若是 newfile 是個大文件,即便刪除,在提交歷史中依然存在。要完全刪除,就要重寫 second 提交以及以後的每個提交,由於以後的提交都有 tree 指向這個大文件,即便刪除,提交的父提交也須要變化。

  1. 完全清除 newfile 以後,second 提交將無效,須要生成一個新提交,second' ;
  2. three 提交的 tree 引用中,也須要刪除 new.cs 的引用,同時修改父提交爲 second' ,生成新提交爲 three' ;
  3. 對於 forth 提交,不用清理 tree 對象,但也須要將父提交修改成 three',獲得新的提交 forth' ;
  4. 以此類推,後面的每個提交都須要修改;

勘誤:這裏的 three,應該是 third 。圖片中也寫錯了,就懶得改了。


原文鏈接:http://www.javashuo.com/article/p-ustuggna-kg.html

END

相關文章
相關標籤/搜索