解剖 .git 資料夾 part. 1 - Git Init

一直以來使用 git 都覺得很神奇,很好奇 git 到底是怎麼樣將整個程式碼和歷史紀錄都存起來的,因此就決定來看看 .git 資料夾裡面到底是藏了什麼樣的檔案來達成這個目的

這一系列文章的目標就是讓大家可以了解 .git 資料夾下的檔案結構與其內容,說不定在哪天可以幫助我們救回操作失誤的檔案


Git init

萬事起頭難,我們首先來看 .git 資料夾是怎麼被產生的。

一般來說我們都不會自己執行 git init 這個指令,實際上在 github 或是其他 git server 在建立專案的時候就會幫我們在 server 上執行 git init --bare 來在 server 上建立好 .git/ 下所需要的檔案,然後在我們 git clone 的時候被下載到本地端的 .git/ 資料夾下

不過這邊我們就試著在一個空資料夾下來執行 git init 來看看效果,下圖是執行 tree .git 後所看到的檔案內容:

files after git init

(這邊使用的是 git v2.41.0 的版本,不同版本可能行為上會有些許的差別)

接下來就讓我們來看一下每個檔案的用途


config

這個檔案裡面放的是針對此 git repo 的 local 設定,初始的內容如下:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true

基本上會先用 [] 切出 section,每個 section 會再有很多的 key = value

如果想要調整設定的話會需要用到 git config 這個指令,細節文件請看這邊

如果我們執行 git config --local alias.co checkout 的話,就會在 alias 這個 section 新增 co = checkout 的設定,打開 .git/config 就會看到:

[alias]
        co = checkout

description

這個檔案基本上只會被 git instaweb 這個指令使用到,預設這個指令會用 lighttpd 來快速架一個網站,讓我們有介面可以瀏覽此 git repo

git instaweb

可以看到有一個欄位是 description ,這邊所顯示的就是 .git/description 這個檔案的內容

git instaweb 還可以用 apache 或其他服務來架站,細節文件請看這邊


HEAD 檔案代表目前所在的 commit 資訊,初始的內容是 ref: refs/heads/master,表示要參考 .git/refs/heads/master 這個檔案裡紀錄的 commit hash,但我們現在才剛初始化,還沒有任何的 commit ,因此也還不會有 .git/refs/heads/master 檔案存在

HEAD 檔裡面也可以直接寫入 commit hash,也就是你執行 git checkout <commit hash> 的時候會發生的事,這時候你也會看到你的 git status 顯示 You are in 'detached HEAD' state.


hooks/

這個資料夾下裝了很多的 git hook 範例,如果想要試用看看的話可以直接將檔案的 .sample 刪除,不同的 hook 有不同的執行時機,例如我們可以在 prepare-commit-msg 來直接幫我們寫好每次 commit 時的固定格式,細節文件請看這邊


info/exclude

這個檔案可以列入不想要被 git 管理的檔案清單,雖然行為與 .gitignore 類似,但這個檔案是不會被 push 到 git server 上,屬於個人設定


其他

剩下的 branch/, objects/, refs/ 下都沒有檔案,我們會在之後的內容再做介紹


Summary

這篇我們介紹了 git init 之後會產生的所有檔案,也簡單瞭解了內容,接下來我們會在新增了 commit 之後再來看看 .git 資料夾有了什麼變化 

覺得不錯的話可以給個拍手

留言

這個網誌中的熱門文章

unit testing 的第一步:使用 gcov/lcov 統計 c++ project 的 testing coverage

在 python 中透過 ctypes 執行 C++ library 的 class

在 blogger 寫 markdown 最接近完美的辦法