轉發學習的啦。git
彷佛不多有人在讀某個git快速教程的時候會說:「這個關於git的快速教程太酷了!讀完了用起git來超級舒服,而且我一點也不怕本身會破壞什麼東西。」web
對git的初學者來講,剛接觸git時就像進入了一個他不會聽/說當地語言的陌生國度。若是你知道本身在哪裏而且知道怎麼走,那就很好。可是若是你迷路了,那麻煩就大了。數據結構
市面上已經有不少關於學習git基本指令的文章,所以這篇文章不講這個。這裏咱們將試着從不一樣的角度來理解。工具
新手們一般都很懼怕git,的確,git確實是一個很強大的工具,但它對使用者並不友好。大量的新概念,一個指令在不一樣的狀況下作徹底不一樣的事情,各類隱含的反饋……學習
我認爲克服這個困難的一個可行方法就是在git的平常commit/puah以外再多作一點工做,若是花點時間來理解一下git是如何產生的,能幫咱們避免不少麻煩。測試
理解.gitspa
當你創建了一個git repo,使用git init,git便建立了一個奇妙的目錄:.git指針
這個文件夾裏包含了git工做時所須要的全部信息。須要明確的是,若是想從你的項目中移除git,但保留項目文件,只須要刪除.git文件夾便可。可是,爲何要這樣作呢?對象
blog
└── tags
這是你第一次commit以前.git文件夾的樣子。
HEAD:這個咱們稍後再說。
config:這個文件夾裏是你的保存設置,這裏將寫入遠程URL,好比你的郵箱、用戶名等。每一次在控制端使用「git config」,它都會在這裏結束。
description:被gitweb (Github的原型)用來顯示對repo的描述。
hooks:這裏有一個有趣的特性。Git有一套能夠自動運行在任何一個有意義的git階段下的腳本,叫作hooks。hooks能夠運行在commit/rebase/pull等等狀態的以前或以後。腳本的名稱決定了它何時被執行。一個有用的pre-push腳本的例子將會被運行以測試控制器(遠程控制)中的全部樣式規則保持一致。
info - exclude:能夠將你不想被git處理的文件放到.gitignore文件夾裏。被排除的文件能夠作到相同的事情,除了它不能被共享。若是你不想將你的自定義IDE關聯到congif文件裏,就可使用這個。雖然大部分狀況下,.gitignore就足夠了。
commit的內部是什麼?
每次你建立了一個文件並跟蹤它,git都會將其壓縮並存儲到本身的數據結構中。這個壓縮對象有一個獨特的名字、一個哈希碼,存儲在對象目錄下。
在研究對象目錄前,咱們要問一個問題,什麼是commit。這裏commit能夠看作是工做目錄的一種快照,但不只僅是快照。
實際上當你commit時,git只作兩件事情來創造你工做目錄的快照:
若是文件沒有修改,git僅僅增長壓縮文件的名字(hash)到快照中。
若是文件被修改過,git就將其壓縮,再將壓縮後的文件存儲到對象文件夾中。而後再添加這個壓縮文件的文件名(hash)到快照中去。
這是一個簡化的描述,實際整個過程會複雜一點。
一旦快照文件被創建,它也會被壓縮並用hash文件命名。那麼這些壓縮文件在什麼地方呢?答案:對象文件夾。
|── 4c
| └── f44f1e3fe4fb7f8aa42138c324f63f5ac85828 // hash
|── 86
| └── 550c31847e518e1927f95991c949fc14efc711 // hash
|── e6
| └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391 // hash
|── info
└── pack
當我建立了一個名爲file_1.txt的空文件並commit以後,對象目錄應該是如上所看到的樣子。請注意若是你的文件的哈希碼是「89faaee…」,git將會吧這個文件儲存在名爲「89」的子目錄下,而且命名這個文件爲「faaee…」。
你看到右邊有3個hash字樣。一個對應的是個人file_1.txt文件,另外一個對應的是我commit時所建立的快照文件。那麼第三個呢?這是由於commit自己也是一個對象,它也會被壓縮並被存儲在對象文件夾中。
記住,一個commit指令實際上包含4件事:
工做目錄的快照文件的名稱(哈希碼)
註釋
提交者信息
Parent commit的哈希碼
而後,大家能夠本身看一下若是不壓縮commit文件時會發生什麼:
// 查看歷史,你會很容易就找到你的commit哈希碼
// 你也沒必要粘貼所有的哈希碼,只要足夠就能夠了
// 創造了獨特哈希碼的字符串
git cat-file -p 4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828
獲得結果:
tree 86550c31847e518e1927f95991c949fc14efc711
author Pierre De Wulf <test@gmail.com> 1455775173 -0500
committer Pierre De Wulf <test@gmail.com> 1455775173 -0500
commit A
你看,正如咱們所指望的,咱們獲得了快照文件的哈希碼、做者信息、和個人commit信息。
這裏有兩件很重要的事情:
正如所指望的,那個名爲「86550…」的快照哈希文件也是一個對象,而且可以在對象文件夾中被找到。
由於這是個人第一個commit,因此沒有Parent。
快照文件本質上是什麼呢?
git cat-file -p 86550c31847e518e1927f95991c949fc14efc711
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file_1.txt
這裏,咱們找到咱們對象存儲器中以前存儲的最後一個對象,咱們快照文件中僅有的對象。這是一個blob,但不是咱們今天要講的。
分支、標籤、HEAD,它們都同樣。