淺析 Git 思想和工作原理

轉載:http://www.lxweimin.com/p/619122f8747b

從根本上來講,Git是一個內容尋址文件系統,并在此之上提供了一個版本控制系統的用戶界面,它是一個非常強大且易用的工具,理解Git的工作原理,能夠幫助我們更容易學習和使用Git。

本文不會像書籍里那樣,一條條討論checkout、branch、remote等諸如此類動詞形式的高層命令和底層命令,本文主要從宏觀方向傳達Git的思想和工作原理,能夠使初學者更加理解,更利于學習。

git

直接記錄快照,而非差異比較

Git 和其他版本控制系統的主要差別在于,Git 只關心文件數據的整體是否發生變化,而大多數其他系統則只關心文件內容的具體差異。這類系統(CVS,Subversion,Perforce,Bazaar 等等)每次記錄有哪些文件作了更新,以及都更新了哪些行的什么內容:

其他系統在每個版本中記錄著各個文化的具體差異

Git 并不保存這些前后變化的差異數據。實際上,Git 更像是把變化的文件作快照后,記錄在一個微型的文件系統中。每次提交更新時,它會縱覽一遍所有文件的指紋信息并對文件作一快照,然后保存一個指向這次快照的索引。為提高性能,若文件沒有變化,Git 不會再次保存,而只對上次保存的快照作一鏈接。Git 的工作方式就如下圖所示。

Git保存每次更新時的文件快照

這是 Git 同其他系統的重要區別。它完全顛覆了傳統版本控制的套路,并對各個環節的實現方式作了新的設計。Git 更像是個小型的文件系統,但它同時還提供了許多以此為基礎的超強工具,而不只是一個簡單的 VCS。

工作區和暫存區

Git 和其他版本控制系統的一個不同之處就是有暫存區的概念。

工作區(Working Directory)

在電腦中能看到的目錄,比如我建立的gittest就是一個工作區

工作區

版本庫(Repository)

工作區中的隱藏目錄.git,就是Git的版本庫。

工作區和版本庫

Git的版本庫里存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。

回憶在我上一篇博客中提到的將文件添加到版本庫的流程圖:

將文件添加到版本庫

通過以上兩幅圖不難看出,需要提交的文件經過add后先都放到暫存區index(或者叫stage)中,然后經過commit指令,一次性提交暫存區的所有修改到head。一旦提交后,暫存區清空,同時若對工作區沒有做任何修改,那么工作區就是干凈的(working directory clean)

文件的三種狀態

對任何一個文件,在Git內都有三種狀態:

已提交(committed):表示該文件已經被安全的保存在本地數據庫中了

已修改(modified):表示修改了某個文件,但還沒有提交保存

已暫存(staged):表示把已修改的文件放在下次提交時要保存的清單中

文件流轉圖

所謂的暫存區域只不過是個簡單的文件,一般都放在 Git 目錄中。有時候人們會把這個文件叫做索引文件,不過標準說法還是叫暫存區域。

我們可以從文件所處的位置來判斷狀態:

Git 目錄中保存著的特定版本文件----->已提交狀態

作了修改并已放入暫存區域----->已暫存狀態

自上次取出后,作了修改但還沒有放到暫存區域----->已修改狀態

重要的 .git 目錄

當一個新目錄或已有目錄執行git init時,Git會創建一個.git目錄。這個目錄包含了幾乎所有Git存儲和操作的對象。若想備份或復制一個版本庫,只需把這個目錄拷貝至另一處即可。對于一個全新的版本庫,該目錄結構如下所示:

目錄結構圖

description文件:僅供GitWeb程序使用

config文件:包含項目特有的配置選項

info目錄:包含一個全局性排除(global exclude)文件,用以放置那些不希望被記錄在 .gitignore文件中的忽略模式(ignored patterns)

hooks目錄:包含客戶端或服務端的鉤子腳本(hook scripts)

HEAD文件:指示目前被檢出的分支

index文件:保存暫存區信息

objects目錄:存儲所有數據內容

refs 目錄:存儲指向數據(分支)的提交對象的指針

關于Git底層命令和高層命令的原理討論,很大一部分都在這個目錄中,要想了解具體的原理,可以看這本書,這里僅僅列出了每部分的功能,有個大體了解。

基本的 Git 工作流程

在工作目錄中修改某些文件。

對修改后的文件進行快照,然后保存到暫存區域。

提交更新,將保存在暫存區域的文件快照永久轉儲到 Git 目錄中。

分析 Git 命令

有了上述介紹,我們可以對 Git 的命令有更深的理解,這里以將文件添加到代碼庫為例進行分析:我們都知道需要兩步,第一步add,第二步commit,但為什么要分兩步呢?每一步都做了什么呢?

(1)git commit -a:相當于運行 git add 把所有當前目錄下的文件加入暫存區域再運行 git commit

(2)git commit :進行一次包含最后一次提交加上工作目錄中文件快照的提交,并且文件被添加到暫存區域

(3)git checkout HEAD -- :回滾到復制最后一次提交

以上僅僅分析了添加文件到代碼庫的過程,更多命令詳解看這里

參考資料

廖雪峰的git在線教程

免費的git書箱 progit2

Git思想和基本工作原理

圖解Git

作者:sunnyaxin

鏈接:http://www.lxweimin.com/p/619122f8747b

來源:簡書

簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 從根本上來講,Git是一個內容尋址文件系統,并在此之上提供了一個版本控制系統的用戶界面,它是一個非常強大且易用的工...
    sunnyaxin閱讀 12,043評論 0 9
  • Git 命令行學習筆記 Git 基礎 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉庫完整的鏡像下來...
    sunnyghx閱讀 3,951評論 0 11
  • Git 基礎 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉庫完整的鏡像下來。這樣一來,任何一處協同...
    __silhouette閱讀 15,942評論 5 147
  • 什么是對象字面量的概念?我就舉例子說明,我就不說文字概念,你能把我怎么樣。就是下面這些寫法。NSNumber *n...
    Stroman閱讀 161評論 0 0
  • 排隊的隊伍,很長,想著不會很快輪到我,便掏出了隨身的大部頭書,看了起來。 正看得起勁,突然感覺后面有人推我,回過頭...
    鳳西閱讀 272評論 0 0