【譯】深入理解git,從研究.git目錄開始

似乎很少有人在讀某個git快速教程的時候會說:“這個關(guān)于git的快速教程太酷了!讀完了用起git來超級舒服,并且我一點也不怕自己會破壞什么東西?!?br>

對git的初學者來說,剛接觸git時就像進入了一個他不會聽/說當?shù)卣Z言的陌生國度。如果你知道自己在哪里并且知道怎么走,那就很好。但是如果你迷路了,那麻煩就大了。

市面上已經(jīng)有很多關(guān)于學習git基本指令的文章,因此這篇文章不講這個。這里我們將試著從不同的角度來理解。

新手們通常都很害怕git,的確,git確實是一個很強大的工具,但它對使用者并不友好。大量的新概念,一個指令在不同的情況下做完全不同的事情,各種隱含的反饋……

我認為克服這個困難的一個可行方法就是在git的日常commit/puah之外再多做一點工作,如果花點時間來理解一下git是如何產(chǎn)生的,能幫我們避免很多麻煩。

理解.git

當你建立了一個git repo,使用git init,git便創(chuàng)建了一個奇妙的目錄:.git這個文件夾里包含了git工作時所需要的所有信息。需要明確的是,如果想從你的項目中移除git,但保留項目文件,只需要刪除.git文件夾即可。但是,為什么要這樣做呢?

第一次commit之前.git文件夾的樣子

HEAD:這個我們稍后再說。

config:這個文件夾里是你的保存設(shè)置,這里將寫入遠程URL,比如你的郵箱、用戶名等。每一次在控制端使用“git config”,它都會在這里結(jié)束。

description:被gitweb (Github的原型)用來顯示對repo的描述。

hooks:這里有一個有趣的特性。Git有一套可以自動運行在任何一個有意義的git階段下的腳本,叫做hooks。hooks可以運行在commit/rebase/pull等等狀態(tài)的之前或之后。腳本的名稱決定了它什么時候被執(zhí)行。一個有用的pre-push腳本的例子將會被運行以測試控制器(遠程控制)中的所有樣式規(guī)則保持一致。

info?-?exclude:可以將你不想被git處理的文件放到.gitignore文件夾里。被排除的文件可以做到相同的事情,除了它不能被共享。如果你不想將你的自定義IDE關(guān)聯(lián)到congif文件里,就可以使用這個。雖然大部分情況下,.gitignore就足夠了。

commit的內(nèi)部是什么?

每次你創(chuàng)建了一個文件并跟蹤它,git都會將其壓縮并存儲到自己的數(shù)據(jù)結(jié)構(gòu)中。這個壓縮對象有一個獨特的名字、一個哈希碼,存儲在對象目錄下。

在研究對象目錄前,我們要問一個問題,什么是commit。這里commit可以看做是工作目錄的一種快照,但不僅僅是快照。

實際上當你commit時,git只做兩件事情來創(chuàng)造你工作目錄的快照:

如果文件沒有修改,git僅僅增加壓縮文件的名字(hash)到快照中。

如果文件被修改過,git就將其壓縮,再將壓縮后的文件存儲到對象文件夾中。然后再添加這個壓縮文件的文件名(hash)到快照中去。

這是一個簡化的描述,實際整個過程會復雜一點。

一旦快照文件被建立,它也會被壓縮并用hash文件命名。那么這些壓縮文件在什么地方呢?答案:對象文件夾。

對象文件夾

當我創(chuàng)建了一個名為file_1.txt的空文件并commit之后,對象目錄應(yīng)該是如上所看到的樣子。請注意如果你的文件的哈希碼是“89faaee…”,git將會吧這個文件儲存在名為“89”的子目錄下,并且命名這個文件為“faaee…”。

你看到右邊有3個hash字樣。一個對應(yīng)的是我的file_1.txt文件,另一個對應(yīng)的是我commit時所創(chuàng)建的快照文件。那么第三個呢?這是因為commit本身也是一個對象,它也會被壓縮并被存儲在對象文件夾中。

記住,一個commit指令實際上包含4件事:工作目錄的快照文件的名稱(哈希碼);注釋;提交者信息;Parent commit的哈希碼。

然后,你們可以自己看一下如果不壓縮commit文件時會發(fā)生什么:

// 查看歷史,你會很容易就找到你的commit哈希碼

// 你也不必粘貼全部的哈希碼,只要足夠就可以了

// 創(chuàng)造了獨特哈希碼的字符串

git cat-file -p 4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828

得到結(jié)果:

tree 86550c31847e518e1927f95991c949fc14efc711

author Pierre De Wulf 1455775173 -0500

committer Pierre De Wulf 1455775173 -0500

commit A

你看,正如我們所期望的,我們得到了快照文件的哈希碼、作者信息、和我的commit信息。

這里有兩件很重要的事情:

1. 正如所期望的,那個名為“86550…”的快照哈希文件也是一個對象,并且能夠在對象文件夾中被找到。

2. 因為這是我的第一個commit,所以沒有Parent。

快照文件本質(zhì)上是什么呢?

git cat-file -p 86550c31847e518e1927f95991c949fc14efc711

100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file_1.txt

這里,我們找到我們對象存儲器中之前存儲的最后一個對象,我們快照文件中僅有的對象。這是一個blob,但不是我們今天要講的。

分支、標簽、HEAD,它們都一樣。

所以,現(xiàn)在你明白了git中的任何事情都可以用一個正確的hash來得到?,F(xiàn)在,讓我們來看一看HEAD。那么,HEAD中又有什么呢?

cat HEAD

ref: refs/heads/master

這不是一個哈希碼,但它有價值,因為HEAD可以被認為是一個指向你正在使用的分支的指針?,F(xiàn)在,我們看一下refs/heads/master內(nèi)部,我們會看到如下信息:

cat refs/heads/master

4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828

是不是很眼熟?是的,這和我們第一次commit時的哈希碼是完全一樣的。這說明

branches和tags無非就是一個指向commit的指針。

這意味著你可以刪除所有你想刪除的branches和tags,而它們所指向的

commit會仍然保留在這里。僅僅是訪問commit更困難一點。

現(xiàn)在你應(yīng)該明白,當你用一堆其它的指令來命令“壓縮”你目前的工作目錄并儲存在對象文件夾時,git實際上都做了些什么。如果你對這些工具足夠熟悉,你就應(yīng)該完全知道哪些文件應(yīng)該包含在commit中,而哪些文件不應(yīng)該。

我的意思是commit并不真的是你工作目錄的快照,而是你想要commit的文件的快照。那么在你保存你想要commit的文件之前,git將它們保存在哪里呢?它將這些文件保存在索引文件。這里我們就不繼續(xù)往下深究了,感興趣的讀者請繼續(xù)研究。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Add & Commit git init 初始化一個 Git 倉庫(repository),即把當前所在目錄變成...
    冬絮閱讀 5,125評論 0 9
  • 朋友整理的,放這里偶爾過來看看 一、基本介紹 首先,Git作為版本控制系統(tǒng),他的原理與SVN為首的集中式版本控制系...
    allenzhan閱讀 1,098評論 0 3
  • 這世上,除了朋友圈外,還有生活。 一、 還沒立秋,你就說要為我織條圍巾,發(fā)來幾張圖片讓我挑,淺藍褐色灰黑,樣樣齊全...
    Young汪楊閱讀 1,962評論 17 31
  • 這個觀點帶動研究人員設(shè)計了測量智力的測試。最著名的(嚴重的缺陷)測試確定經(jīng)過移民后,美國成年白人的平均心理年齡為1...
    柳濤虹閱讀 211評論 1 3

友情鏈接更多精彩內(nèi)容