Git 思想和工作原理


從根本上來講,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 工作流程

  1. 在工作目錄中修改某些文件。
  2. 對修改后的文件進行快照,然后保存到暫存區域。
  3. 提交更新,將保存在暫存區域的文件快照永久轉儲到 Git 目錄中。

分析 Git 命令

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


 

(1)git commit -a:相當於運行 git add 把所有當前目錄下的文件加入暫存區域再運行 git commit
(2)git commit <file_name>:進行一次包含最后一次提交加上工作目錄中文件快照的提交,並且文件被添加到暫存區域
(3)git checkout HEAD -- <file_name>:回滾到復制最后一次提交



作者:sunnyaxin
鏈接:http://www.jianshu.com/p/619122f8747b
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM