深刻理解Git內部原理

前言

當咱們執行git init命令,或者clone網上某個代碼倉庫後,會看到有一個.git目錄,git全部版本控制信息就是放在目錄裏面,下面對這個.git目錄進行分析。git

.git目錄

  • hooks:鉤子目錄,存放執行指定git命令前或者後觸發的腳本,能夠看到默認會有幾個sample文件,若是要開啓某個鉤子腳本,就把腳本文件名的後綴simple去掉就能夠,這些鉤子會在特定的時機被觸發執行,好比post-commit在整個提交過程完成後執行,能夠用於發送提交通知等,另外也有服務端鉤子,在推送前或者後執行,好比post-receive在推送結束後會被執行,能夠用於通知打包平臺啓動打包任務。關於git鉤子更詳細的信息能夠參考:自定義 Git - Git 鉤子算法

  • info:保存git的相關信息網絡

  • logsssh

    • refs:暫存記錄,本地分支記錄,遠程分支記錄post

    • HEAD:記錄每次的變動操做版本控制

  • objects:存放真實數據,以Git對象形式存放指針

  • refs對象

    • heads:存放全部本地分支最新的commit哈希值進程

    • stash:存放stash對應的哈希值開發

    • tags:存放tags相關的

  • config:配置文件

  • HEAD:當前分支,並不存放SHA1值,相似/refs/heads/master,這個指向的文件裏會有最新commit的SHA1值

  • index:二進制文件,暫存區

Git中的幾種對象

  • 數據對象

    數據對象就是用於存儲真實的文件數據,其建立過程以下:

    1. 計算內容大小,構造header

    2. 將header添加到內容前面,構造數據對象

    3. 使用sha1算法計算Git對象的160位hash碼,表示成16進制就是40位

    4. 使用zlib的deflate算法壓縮數據對象

    5. 存儲到.git/objectes/目錄下,文件夾名爲hash碼的前兩位,文件名爲hash碼的後38位

  • tree對象

    保存目錄信息,也就是目錄樹的非葉子節點的版本控制信息,須要從暫存區中建立。

  • commit對象

    保存某次提交的詳細信息,包括時間、提交人等。

  • tag對象

    跟commit對象相似,包含了一個指針,該指針指向一個commit對象,並且永遠不會改變。

Git提交過程原理

  1. 添加到暫存區:git add xxx

    • 建立數據對象

    • 更新index文件

  2. 提交:git commit -m "xxxx"

    • 若是存在目錄,就建立tree對象

    • 建立commit對象

  3. 將上面建立的對象保存爲目錄和文件

能夠看到,git提交的整個過程,其實就是建立數據對象、tree對象和commit對象的過程,最終這些對象都會保存到objects目錄下。

Git數據存儲原理

Git默認採用的是鬆散對象格式,也就是每次保存一份完整數據,好比有個大文件10MB,第一次提交被保存起來了,後面修改了一點東西又提交,這時Git會保存兩個10Mb的對象數據,這樣看起來就會比較浪費,最好是可以只保存文件的差別部分。

實際上Git就是這樣作的,若是存在太多的鬆散對象,或者執行了push命令,或者git gc命令,Git就會將鬆散對象進行打包到一個pack文件中,該文件保存文件不一樣版本之間的差別內容,減小了存儲佔用,並且是該pack文件是二進制文件,須要採用命令git verify-pack查看。

注意這裏pack會將最新版本保存爲完整對象,而以前的版本保存差別信息,由於大部分狀況下訪問的都會是最新版本。

Git傳輸協議

Git有四種傳輸協議,包括本地協議、HTTP協議,SSH協議,GIT協議。

  • 本地協議

    遠程倉庫就存放在硬盤中,這裏的硬盤,能夠是遠程掛載的網絡硬盤,遠程倉庫的地址直接指定爲目錄路徑,也能夠加上file前綴。不過共享文件系統配置起來比較麻煩,速度也比較慢。

  • HTTP協議

    採用http/https協議進行傳輸,這裏細分有兩種協議:啞協議和智能協議,啞協議是Git 1.6.6版本以前使用的協議,Git 1.6.6引入了智能協議。

    • 啞協議

      1. 獲取info/refs文件,肯定全部分支的最新commit的SHA1值

      2. 獲取HEAD文件,肯定當前分支,檢出到工做目錄

      3. 獲取第一個commit對象的數據

      4. 往上追溯,獲取全部對象數據

    • 智能協議(大部分使用)

      無論是上傳(好比push等)仍是下載(好比pull等),都是客戶端開一個進程,服務端開一個進程,而後協商須要傳輸的數據,確認好哪些數據須要傳輸,進程端口是http或者https端口。

    HTTP協議的優勢:1.就是使用方便,只須要一個遠程地址便可,2.認證方便,直接輸用戶名密碼,不須要像SSH首次配置那麼麻煩。

  • SSH協議

    使用ssh協議作爲傳輸協議,使用時須要配置ssh信息,配置後就不用每次都輸入用戶名和密碼了。

  • Git協議

    與http智能協議原理相似,但它監聽的端口是9418,Git協議沒有受權機制,也就是不能實現控制一部分人能push,另外一部分不能push,所以大部分狀況的作法是讓Git協議只開放讀取,禁止推送。

git flow協做流程

穩定分支

  • develop:開發分支

  • master:發佈分支

臨時分支

  • feature:特性分支,用於臨時開發新功能,從develop拉,最終合入到develop。

  • release:預發佈分支,當develop分支開發完本版本需求後,就拉release分支,用於修bug,配置發佈信息等,這時develop分支繼續開發下一版本的需求。當release分支修改結束後,就合入develop和master。注意合入到master時要打tag作標記,好比master_8.1之類的命名。

  • hotfix:修復分支,用於修復線上緊急bug,從master拉,最終合入到develop和master。注意合入到master時要打tag作標記,好比master-8.1.1之類的命名。

相關文章
相關標籤/搜索