深入理解Git - Git底層對象


前篇:
深入理解Git - 一切皆commit

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

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

git 文件系統

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

blob object(數據對象)

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

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

tree object (樹對象)

相當於文件系統中的文件夾。

commit object(提交對象)

提交對象可以理解為對樹對象的一層封裝,里面包含了提交時間,提交作者等信息,更重要的,里面包含了父提交的ID,由此就可以形成 git 提交的有向無環圖。


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

這里,我們並沒有發現分支這些概念,回顧之前說的『一切皆 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 。圖片中也寫錯了,就懶得改了。


原文連接:https://www.cnblogs.com/jasongrass/p/10582465.html

END


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM