鍍金池/ 問答/Linux  HTML/ 如何理解.git文件夾下的objects文件?

如何理解.git文件夾下的objects文件?

對于git的原理我的理解是:git在每次commit的時候都會生成一個tree對象、一個parent對象(如果不是第一次提交的話)、和一個commit對象,這個最頂層的tree就是對應整個工作目錄,tree下面還有blob、tree對象,都是一串hash值指向對應的內容,當某個文件發(fā)生變動的時候會重新保存一次快照,如果文件沒有發(fā)生變動,保留的快照依然是上次的。

所有的數(shù)據(jù)都是保存在objects中的,那么我每次提交豈不是都要生成一個新的文件(因為每次的commit都是不一樣的)?那么整個項目在經歷過無數(shù)次提交之后objects文件的內容會越來越多.....

但是我看了一下項目中的objects中的文件并沒有很多,為什么會這樣呢?而且在我理解中每次commit在objects中只會生成一個文件文件名就是每次commit hash值的前兩位,但是實際上會生成三個文件夾?這又是為啥?


分割線:
我在本地新建git倉庫,文件夾下只有一個txt文件

clipboard.png

現(xiàn)在我提交一次commit,log如下

clipboard.png

然后執(zhí)行

git cat-file -p c6298e6493a3096dc5dd9

clipboard.png

可以看到這里有個tree對象hash值為ba65d8..,我再對這串hash執(zhí)行:

git cat-file -p ba65d80b3655f4

clipboard.png
這里可以看到一個blob對象也對應一個hash值,然后我在對此hash執(zhí)行

git cat-file -p ea4fff75dac5abe33d1ac53

clipboard.png
最后這個引用指向的就是文件的內容。

通過以上操作我個人理解如下:
之前說的git有三個對象,tree、blob、commit,通過測試我覺得這三個對象不是平級關系,在提交一次commit后,生成一個commit對象,這個commit對象下面有一個頂層的tree對象,然后tree對象下面再包含tree對象或者blob對象。最底層的blob對象就是文件的內容

而且git就是依照這些對象的hash值找到對應的文件,記錄每次commit的狀態(tài)。每次提交commit后變化的文件都會保存一個新的快照(hash),沒有發(fā)生變化的文件依然保留原來的快照(hash)值。

回答
編輯回答
清夢

為什么objects中的文件沒有很多?

Git 往磁盤保存對象時默認使用的格式叫松散對象 (loose object) 格式:即每次修改一個文件,除了保留舊blob對象,還會生成一個含有完整內容的新blob對象。Git 時不時地將這些對象打包至一個叫 packfile 的二進制文件以節(jié)省空間并提高效率:Git 打包對象時,會查找命名及尺寸相近的文件,并只保存文件不同版本之間的差異內容。當倉庫中有太多的松散對象,或是手工調用 git gc命令,或推送至遠程服務器時,Git 都會這樣做。 打包后,.git/objects中的對象就被移除了,剩下多是沒有被任何commit包含的對象。

每次commit在objects中生成三個文件夾?

這跟你的文件結構有關系。 commit操作一定會增加 commit對象, 以及代表根目錄的tree對象。 若你的修改的文件層級比較深,有多少層級就生成多少個tree對象。
每個對象以文件夾的形式展示出來。

或者也跟你的理解有關? 你更新了問題,只有一個單一文件,在根目錄下,那么文件本身是個blob,它在一個tree下(按照你題目的補充,它就是根目錄),然后還有一個commit對象。 一共三個。

2017年4月27日 00:12