# Git ## HEAD是什麼東西? #### HEAD是一種**指標**,指向某一個分支,可以把HEAD當作『目前所在分支』。 ![](https://i.imgur.com/GPMtH45.png) `$cat .git/HEAD` `ref: refs/heads/master` 此時HEAD指向master分支 `$cat .git/refs/heads/master` `874b6a091b25c03ab7ee22772c7c67df2d7e9faf` master檔案 ## .git裡有什麼? #### 四個物件分別為 **Blob物件** **Tree物件** **Commit物件** 與 **Tag物件** 步驟: 1. 建立檔案,而內部放入字串"Git test" `$echo "Git test" > index.html` 2. 將檔案加入暫存區域(Staging Area) `$git add index.html` 3. 計算"Git test"字串的SHA-1值 `$echo "Git test" | git hash-obje ct --stdin` ![](https://i.imgur.com/o9nNlfl.png) SHA-1值中前2個字為目錄(ed),剩餘的38個字是檔名 ![](https://i.imgur.com/VGFnkpg.png) `$git cat-file -t`知道型態 `$git cat-file -p`知道內容 ![](https://i.imgur.com/UEczAY5.png) ##### git add運作流程 1. 加入暫存區後,會依據內容計算出SHA-1值 2. 會依照SHA-1值前2個字建立目錄,剩餘的則當成檔案名稱。並存放在.git/objects 3. 檔案的內容使用壓縮演算法,把原本內容壓縮後的結果 --- `$mkdir config` 建立一目錄 config `$git status` 查詢目前狀態 ![](https://i.imgur.com/1g4w8dO.png) **空的目錄無法加入到Git之中** ![](https://i.imgur.com/fNmRipO.png) `$touch config/database.yml` 但若此時在目錄內加入空檔案後,就會顯示在為追蹤檔案上 `$cat config/database.yml | git hash-object --stdin` 計算此檔案的SHA-1值後,獲得 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 檔案排列方式與前例相同,但目錄部分git又該如何記錄? ##### git commit 在執行commit之後,objects內則多了檔案 ![](https://i.imgur.com/9E8XKU2.png) `$git cat-file -t 06398e15e4966eb2762ce3c2af184a33810607fc` 回傳一個tree物件 `$git cat-file -p 06398e15e4966eb2762ce3c2af184a33810607fc` ![](https://i.imgur.com/uR0GRer.png) ![](https://i.imgur.com/0bY8XAq.png) 1. Git將檔案以Blob物件存放 2. 檔案名稱與目錄會以Tree物件存放 3. Tree物件內容指向某個Tree物件或者是Blob物件 由於這些物件之間並無上下層關係,因此此圖稱為[Directed Acyclic Graph(DAG),有向無環圖](https://zh.wikipedia.org/zh-tw/%E6%9C%89%E5%90%91%E6%97%A0%E7%8E%AF%E5%9B%BE) 在剛剛commit過程中還有多一個檔案 `$git cat-file -t 6db6945f9f0267e374cc98702262b9942f72c33c` 回傳一個commit物件 `$git cat-file -p 6db6945f9f0267e374cc98702262b9942f72c33c` 內容為 ![](https://i.imgur.com/5stRtAj.png) ![](https://i.imgur.com/UCwoFHQ.png) Commit物件會指向Tree物件 --- ##### 修改檔案內容 首先我們先將原本index.html內容進行修改,並且進行add與commit動作。 經過`$cat index.html | git hash-object --stdin`得到0341571e1a638abbf83330127f18f5cfde48f3f5 ![](https://i.imgur.com/RuMbzT8.png) 查看檔案內多的物件內容 ![](https://i.imgur.com/JpxeHSF.png) 會多了Tree物件跟Commit物件 ![](https://i.imgur.com/MJclj4Q.png) Commit物件會指向Tree以外還有前一個Commit物件 --- ##### git tag 使用`$git tag -a tag_here -m"tag在這"`在當前Commit加上tag後 會在Objects資料夾多出檔案 ![](https://i.imgur.com/B6VW1pR.png) ![](https://i.imgur.com/Z7edx5y.png) --- #### 總結: * 檔案在Git中會以Blob物件儲存 * 目錄和檔名會以Tree物件儲存。而Tree可以指向Blob物件或者其他Tree物件 * Commit物件會指向Tree物件,也會指向前一個Commit物件(如果不是第一個Commit的話) * Tag物件會指向某個Commit物件 * 分支不屬於四大物件但會指向Commit物件 * HEAD不屬於四大物件,但會只向某個分支 * 當git push推送後,會在.git/refs底下多出remote目錄,裡面存放遠端分支,概念與本地相同