Git 工作原理
Git 是最先進(jìn)的開源分布式版本控制系統(tǒng),最初由 Linus 為解決 Linux 的代碼管理而發(fā)明。版本控制系統(tǒng)(Version Control System, VCS)有很多實現(xiàn),比如早期的 CVS,主要用于控制、協(xié)調(diào)文件的一致性。目前使用最多的主要是 SVN 和 Git。
SVN vs Git
SVN 是 subversion 的縮寫,使用一個中央版本庫來進(jìn)行集中控制并記錄文件變更歷史,支持多個分支并行開發(fā),采用了客服端/服務(wù)器模式,文件的各個版本、分支都儲存在服務(wù)器上。SVN 采用的是 Copy-Modify-Merge(拷貝-修改-合并)模式對文件進(jìn)行管理。
在 Copy-Modify-Merge 模式下,當(dāng)用戶想修改文件時,先將服務(wù)器文件 update 到本地,然后在本地對副本進(jìn)行修改,修改完成后,再將副本 commit 到服務(wù)器。如果 commit 前其他用戶修改了文件,則文件版本號發(fā)生沖突,需要先 update 到本地進(jìn)行合并,才能繼續(xù) commit。
與 SVN 不同,Git 是分布式版本管理系統(tǒng)。從 Git 服務(wù)器 clone 文件到本地,成為本地倉庫,包含了全部文件和變更記錄,與之相對的服務(wù)器倉庫被稱為遠(yuǎn)程倉庫。當(dāng)用戶想修改文件時,直接對本地副本進(jìn)行修改,修改完成后把改動 commit 到本地倉庫,需要同步時再 push 改動到遠(yuǎn)程倉庫。由于使用本地倉庫,Git 減少了很多網(wǎng)絡(luò)開銷,使得性能比 SVN 有極大的提升,即使在斷網(wǎng)情況下也能繼續(xù)工作。
大多數(shù) VCS 應(yīng)用是基于增量的版本控制,即存儲了文件信息和對每個文件所做的更改。而 Git 是基于快照的版本控制,在每個版本都記下文件的快照,并存儲對快照的引用。為了提高效率,如果文件沒有更改,Git 不會再次存儲該文件,而只是指向它已經(jīng)存儲的先前相同文件的鏈接。因此,本質(zhì)上,Git 是一套內(nèi)容尋址(content-addressable)文件系統(tǒng)。

Git 倉庫
Git 中的文件和操作都以 Git 對象來保存。Git對象分為 BLOB、tree 和 commit 三種類型,BLOB對象可以存儲幾乎所有的文件類型,tree對象是用來組織BLOB對象的一種數(shù)據(jù)類型,commit對象表示每一次的提交操作。commit對象存儲了對tree對象的引用,tree對象存儲了對BLOB對象的引用。進(jìn)行版本控制所需要的所有數(shù)據(jù)都在 .git 文件夾中,如圖所示。

.git 文件夾核心文件包括:config文件、objects文件夾、HEAD文件、index文件以及refs文件夾。
config文件:主要記錄針對該項目的一些配置信息,例如是否以bare方式初始化、remote的信息等;
objects文件夾:主要包含git對象,保存在以其sha-1值的前兩位為子文件夾、后38位為文件名的文件中。為了節(jié)省磁盤空間,會定期對Git對象進(jìn)行壓縮和打包,并存儲在pack文件夾中,相關(guān)的查找信息存儲在info文件夾中;
refs文件夾:存儲指向分支的 commit 對象的指針。其中heads文件夾存儲本地每一個分支最近一次commit的sha-1值,每個分支一個文件;remotes文件夾記錄最后一次推送到遠(yuǎn)程倉庫的每個分支的值;
HEAD文件:存儲當(dāng)前分支在 refs 中的信息,如ref: refs/heads/master;
index文件:存儲暫存區(qū)域(staging area)的信息,內(nèi)容包括文件的時間戳、文件名、sha-1值等;
Git 文件狀態(tài)
Git 的文件有已提交(committed)、已修改(modified) 和已暫存(staged)三種狀態(tài)。
已修改表示修改了文件,但還沒保存到倉庫中;
已暫存表示對一個已修改文件的當(dāng)前版本做了標(biāo)記,使之包含在下次提交的快照中;
已提交表示數(shù)據(jù)已經(jīng)安全地保存在本地倉庫中;
與之對應(yīng),Git 中還有工作區(qū)(Working Directory)和暫存區(qū)(Staging Area)。工作區(qū)存放從倉庫 checkout 出來的文件,用戶可以進(jìn)行修改。下次將要 commit 的文件信息存儲在暫存區(qū)。commit 操作實際上是從暫存區(qū) commit 到本地倉庫中。

Git 命令
在 Git 中,包括 porcelain 命令(高層命令)和 plumbing 命令(底層命令)兩種類型。按照最初的設(shè)計,Git 是一個工具集,底層命令用于以 UNIX 風(fēng)格使用或由腳本調(diào)用。高層命令用于方便用戶進(jìn)行操作。我們平時使用的都是高層命令,內(nèi)部實際上封裝了底層命令的調(diào)用。
Git 的常用命令如圖所示。首次從遠(yuǎn)程倉庫創(chuàng)建本地倉庫使用 clone 命令;使用 checkout 命令從本地倉庫切換分支到工作區(qū);增加文件后,使用 add 命令提交變更到暫存區(qū);修改完成后,使用 commit 命令提交變更到本地倉庫;需要同步時,使用 push 命令推送變更到遠(yuǎn)程倉庫;遠(yuǎn)程倉庫變化后,使用 pull 命令拉取變更到工作區(qū)。以上這些命令都是高層命令。

當(dāng)我們執(zhí)行 git add 高層命令時,內(nèi)部實際上封裝了 git hash-object 和 git update-index 兩個底層命令。其中 git hash-object 將需要暫存的文件進(jìn)行 key-value 轉(zhuǎn)化生成 git 對象,存儲到 objects 文件夾中,獲取了這些文件的 key,git update-index 命令把這些文件存儲到暫存區(qū)。
當(dāng)我們執(zhí)行 git commit 高層命令時,內(nèi)部實際上封裝了 git commit-tree key –p key2 底層命令。該命令創(chuàng)建 commit 對象,并掛載到前繼對象之后。
—?【 THE END 】— 本公眾號全部博文已整理成一個目錄,請在公眾號里回復(fù)「m」獲取! 3T技術(shù)資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號內(nèi)回復(fù)「1024」,即可免費(fèi)獲?。?!
