一個 .git 目錄,領悟 Git 的強大!

原文:https://www.daolf.com/posts/git-series-part-1/
作者:Pierre de Wulf
譯者:明明如月,責編:郭芮


來源:CSDN(ID:CSDNnews)

Git 是一個強大的工具,但是使用起來卻不是很友好。如果程序員們能夠真正花時間去理解 Git 的構成,將會避免很多不必要的麻煩。



初學 Git 就像一個不懂當地語言的人來到一個陌生的國家——如果你知道自己在哪,該去哪裡,那還好。一旦你迷路了,那麻煩就大了。


網上有很多學習 Git 基本命令的文章,但是本文並不屬於這一類文章。我在此處將嘗試提供一個不同的學習思路。


初學者一般都很害怕 Git,很難不怕。毫無疑問,Git 是一個強大的工具,但是使用起來卻不是很友好。使用 Git 要理解很多新的概念,將文件作為命令參數和不作為參數兩者的含義大相徑庭。


我認為要想克服這些困難,不僅要學習 Git 的 commit 和 push 的用法。如果我們能夠真正花時間去理解 Git 的構成,將會避免很多不必要的麻煩。


一、研究 .git 目錄


好的,我們現在開始吧。


當你通過 git init 創建 git 倉庫時, git 就會創建 .git 目錄。該目錄包含讓 git 能夠正常工作所需的所有信息。直白點說,如果你不想在項目中繼續使用 git ,直接將 .git 目錄刪除只保留項目文件即可。但是為什麼這樣做就可以呢?


下面是你第一次提交後 .git 文件夾的樣子:


一個 .git 目錄,領悟 Git 的強大!

HEAD


後面再講。


config (配置)


該文件包含你的倉庫配置,比如遠程的 url ,你的郵箱和用戶名等。每次你在控制檯使用 git config... 都會對這裡產生影響。


description(描述)


供 gitweb ( github 的一種前身) 使用,顯示倉庫的描述。


hooks (鉤子)


這是一個有趣的特性。Git 提供了一套腳本,可以在每個有意義的 Git 階段自動運行。這些被稱為鉤子的腳本可以在提交 (commit)、變基 (rebase)、拉取 ( pull ) 操作的前後運行。腳本命預示著它的執行時機。如我們可以編寫 pre-push 的作為鉤子,進行推送代碼前的檢查。


info (信息)


你可以將不想被 git 管理的文件記錄到 .gitignore 文件中。排除文件的意思是不想共享這個文件。例如你不想共享你的 IDE 自定義配置,將其添加到 .gitignore 文件中即可。


二、一次提交包含哪些內容?


每次你創建一個文件,並追蹤它,git 都將把文件進行壓縮並存儲在自己的數據結構中。被壓縮的對象將具有唯一的名稱和 hash 值,並將存儲到對象 (object) 目錄中。


在研究對象目錄之前,我們必須明白一次提交的含義是什麼。你可能會說,一次提交就是當前工作目錄的一個快照,但事實遠不止如此。

實際上,當你提交時,git 通過下面兩個步驟對你的工作目錄創建快照:


如果文件沒啥變化,git 只是將壓縮的文件(哈希值)添加到快照中。


如果文件發生了變化, git 將對其進行壓縮並將其存儲在 object 文件夾。最終,將這個壓縮文件的名稱(哈希值)添加到快照中。


這裡給出一個簡化的過程,實際上整個過程有點複雜,將在以後的文章中給出詳細的介紹。


一旦快照被創建出來,它將會被壓縮,以哈希值命名。那麼這些壓縮的對象存在哪裡呢?他們被存在 object 文件夾中。


一個 .git 目錄,領悟 Git 的強大!

這是我創建了一個空的文件 1.txt 並提交後 object 文件夾的樣子。請注意,如果你的文件哈希值為 "4cf44f1e…",git 會將其存儲到 "4c"子目錄中,並將其命名為"f44f1…"。這個小技巧,將 /objects 目錄的數量減少到 255 個以內。


你要記住的是,一次提交包含 4 個部分:


  1. 工作目錄快照名稱(一個哈希值)。
  2. 一條評論/註釋。
  3. 提交者信息。
  4. 父提交的哈希值。


如果我們解壓提交的文件:


<code>// 通過查看提交歷史,你可以輕鬆地查詢到提交的哈希值  
// 你都不需要複製完整的哈希值字符串,  

// 複製能夠保證哈希值的唯一性的前面一段即可。  
git cat-file -p 4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828  /<code>


得到下面的內容:


<code>tree 86550c31847e518e1927f95991c949fc14efc711  
author Pierre De Wulf <test> 1455775173 -0500  
committer Pierre De Wulf  1455775173 -0500  

commit A  
/<test>/<code>


正如預想的一樣,我們看到了快照的哈希值、作者信息和提交的註釋。


有兩個非常重要的事項:


  • 正如所預想的那樣,快照的哈希 "86550…" 也是一個對象,你可以在對象文件夾中找到它。
  • 因為這是第一次提交,所以沒有父提交的哈希值。


那麼,在快照中存的是啥呢?


<code>git cat-file -p 86550c31847e518e1927f95991c949fc14efc711  

100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file_1.txt  /<code>


我們找到之前存儲的最後一個對象,也是我們快照中的唯一的一個對象。它是一個 blob 對象,這是另外的知識點,不在這裡討論。


三、分支, 標籤, HEAD 都一樣


你現在已經瞭解到,git 中的所有內容都可以通過正確的哈希值來獲取到。現在讓我們聚焦於 HEAD。那麼什麼是 HEAD?Git 高級用法,喜歡就拿去用。


<code>cat HEAD  
ref: refs/heads/master  /<code>


HEAD 不是一個哈希,HEAD 可以理解為指向你正在使用的分支的頂端的指針。我們接下來看下 refs/heads/master:


<code>cat refs/heads/master  
4cf44f1e3fe4fb7f8aa42138c324f63f5ac85828  /<code>


看起來眼熟嗎?這和我們第一次提交的哈希值相同。這表明分支 ( branch) 和標籤 (tag) 只不過是一個指向提交的指針。這就意味著,即使你刪掉了你要刪除的分支和標籤,他們指向的提交依然還在那裡,只不過刪除後難獲取這些提交更困難一些。如果你想了解更詳細的內容,可以通過 git book 來學習。


四、寫在最後


所以學到這裡,你應該明白 git 提交就是把你當前工作目錄的文件“壓縮”,然後將其和其他信息一起存儲到對象文件夾中。如果你對 git 足夠熟悉,你就會知道哪些文件會包含在提交中,哪些文件不會被提交。


我這裡說的提交,並不是指你的工作目錄快照,而是指你要提交的文件快照。在實際執行之前,git 會在哪裡存儲你要提交的文件?


它將他們存儲到索引文件中。不過,我們暫時不打算深入研究它。如果你真的感興趣,可以通過這裡

(https://github.com/git/git/blob/master/Documentation/technical/index-format.txt)深入學習。


感謝閱讀!希望通過閱讀本文,你能夠學到有價值的內容。希望本文能夠幫你更輕鬆地使用 git。


分享到:


相關文章: