1. 程式人生 > >程式設計師必備技能之 Git 的體系結構與歷史

程式設計師必備技能之 Git 的體系結構與歷史

640?wx_fmt=gif

十幾年前,Linux 之父 Linus Torvalds 在個人休假時,發現自己掌控下的 Linux 核心在開發過程中遇到了一些問題,於是鬱悶無比,經過多天的琢磨與實踐之後研發出一款小工具——Git,以望幫助更多的開發者有效、高速地處理從很小到非常龐大的專案版本管理。萬萬沒想到,經過多年的發展之後,彼時名不經傳的 Git 如今早已佔據行業的主導地位,而這其中到底經歷了些什麼?

640?wx_fmt=jpeg

作者 | Will Hay Jr.

譯者 | 樑蕊

責編 | 屠敏

出品 | CSDN(ID:CSDNNews)

截至 2018 年,全球知名的 IT 技術問答網站 Stack Overflow 調查的 74000 開發人員中,將近 90% 的人表示更喜歡使用 Git 進行版本控制。根據調查,Git 在其他所有分散式版本控制系統中占主導地位,並且從 2017 年開始使用率幾乎增長了 20%。然而,Git 並不總是像這樣普及。讓我們一起看看它上升到大眾化的歷程。



640?wx_fmt=png

早期歷史


Git 誕生於 Linux 核心社群對可用的 VCSs(版本控制系統)的挫敗感。Linux 核心的發展在當時是相當不尋常的:專案中有大量的貢獻者而且貢獻者的參與程度和對程式碼知識庫的瞭解有很大的差異。由於 Linux 核心不尋常的發展狀況,開發人員很難找到適合他們需求的 VCSs(版本控制系統)。於是他們選擇了 BitKeeper 和併發修訂系統(CVS),每個系統有一組核心開發人員去負責管理核心的開發。BitKeeper 提供分散式版本控制,而 CVS 是一個客戶端-服務端版本控制系統,它可以讓開發人員“簽出”專案的副本,進行更改,然後將他們的改變“簽入”到服務端。

640?wx_fmt=png

在 2005 年初期,BitKeeper 的版權持有人 Larry McVoy 宣佈撤銷允許免費使用 BitKeeper 軟體的許可。他聲稱,正在建立與 BitKeeper 反向互動軟體的澳大利亞程式設計師 Andrew Tridgell 反向設計了 BitKeeper 的原始碼,這樣違背了它的許可。許多依賴 BitKeeper 免費軟體去開發 Linux 核心的 Linux 核心開發者現在已經無法繼續使用它了。

Linux 社群與 BitKeeper 的關係已經開始有了衝突,但是他們希望在離開 BitKeeper 之前有一個可行的選擇。Linux 核心主要的開發人員 Linus Torvalds 在看到沒有其他免費的選擇可以滿足他們的需求之後就開始開發一個新的 VCS。在傳送到核心郵件列表的電子郵件中,Linus 表示了他對 BitKeeper 有多麼滿意和 BitKeeper 為 Linux 核心開發做了什麼,主要是它幫助整個團隊更細粒度的保留了一些更改和更改追蹤集的檢視。值得注意的是,雖然 BitKeeper 沒有成功,但它依然在改進核心開發方式上非常有幫助。


640?wx_fmt=png

早期發展


為了向團隊提供 BitKeeper 的替代品,Linus 概述了一些新版本控制系統的某些設計標準。他想要保持 BitKeeper 提供給團隊的一些好處,同時進行一些改進。

640?wx_fmt=jpeg

他主要強調了三個主要特徵:防止內容腐敗的保障措施、高可用性和分散式開發工作流。Linus 還強調了補丁不應該超過 3 秒,引用源控制管理系統,該系統需要花費 30 秒來推送補丁並且更新相關的元資料。對於從事開發 Linux 核心的 250 名開發人員來說,這樣的一個系統,顯然不能很好的擴充套件。儘管 BitKeeper 對 Git 的建立有早期的影響,但 Git 比 BitKeeper 允許更多的分散式和本地工作流。專案協作者可以在儲存庫離線工作,增量提交,確定何時釋出他們的工作,選擇共享哪些更改,並將他們的更改推送到不同的分支。


640?wx_fmt=png

架構概述


一個版本控制系統通常有三個核心功能,所有的這些功能都被 Linus 內建在 Git 中。它必須能夠儲存內容、追蹤對內容所做的更改(所有的歷史紀錄,包括合併元資料)、與專案協作者選擇分發內容和提交歷史記錄。

640?wx_fmt=png

Git 使用了有向無環圖(DAG)進行內容儲存以及提交和合並歷史記錄。DAG 是一個有著有限數量的頂點和邊(頂點之間的連線),沒有包含迴圈的有向圖(是非週期性的)。非迴圈意味著沒有辦法從A節點到B節點,並通過任意數量的邊返回到 A 節點。DAG 也必須有拓撲排序,這意味著在一個序列中,所有的頂點都有直接從最開始的節點指向最後節點的邊(如下圖中箭頭從左上角指向右下角所示)。

640?wx_fmt=png

Git 還將這種有向無環圖結構應用在儲存內容上。Git 實質上是一個可定址的檔案系統,它由構成層次結構的物件組成,這些層次結構反映了內容的檔案系統樹。Git 有三種主要的原始內容,它用來表示儲存庫儲存的內容:樹、blob和提交。所有的內容實質上都作為樹或 blob 物件儲存。Blob 是儲存在儲存庫中的檔案,樹物件引用了其他子樹或者 blob。你可以認為 blob 是儲存內容的檔案,而樹就像是目錄。在另一方面,提交物件有三個主要的屬性,它指向了在提交時代表專案頂級快照水平的檔案系統樹、它還包含對它之前提交的引用,提交作者的欄位和可選的提交資訊。

所有這些物件基元都有 40 位的 SHA 雜湊。兩個相同的物件將會有相同的雜湊值,不同的物件將會有不同的雜湊值。通過使用 SHA 雜湊作為參考標識, Git 能夠有效的計算差異。為了防止資料損壞,可以重新計算一個物件的雜湊值,以便輕易的識別出損壞或丟失的資料。

640?wx_fmt=png

Git 還使用了有向無環圖來追蹤內容更改的歷史記錄。如上所述,每一個提交物件都包含它祖先的元資料,也就是說一次提交可以有任意數量的父提交。Git 使用有向無環圖的特性來儲存內容、保留歷史追蹤記錄和合並歷史記錄,這樣允許它保留完整的分支功能,因為檔案的歷史記錄將其目錄結構一直鏈接到根目錄和提交物件。


640?wx_fmt=png

分支策略


640?wx_fmt=png

當我們將“feature7”分支合併到 master 分支時,Git 會執行“fast-forward”合併策略,向前移動主分支指標。只有將當前“feature7”分支的提交歷史記錄要合併到 master 分支的最新提交時,才會使用“fast-forward”合併。

640?wx_fmt=png

當你所在分支的提交併不是你正在合併的分支的直接祖先時,Git 使用不同的合併策略,這意味著你的開發歷史不同。在這種情況下,Git 使用“遞迴”策略並執行三向合併。Git 建立了檔案狀態的新快照和指向新快照的分支提交物件。此時這個合併提交物件有兩個父類,指向兩個分支的頭部的提交物件被合併在一起。Git 使用非線性內容儲存策略和提交歷史記錄的系統,可以將專案的兩個分支無縫的合併在一起。


640?wx_fmt=png

分佈和初始化


Git 使用分散式模型處理專案協作者之間的內容和歷史分佈,使用者可以離線工作並在本地儲存庫上進行提交。每個協作者都有一個 Git 儲存庫的副本,他們可以離線工作,進行更改,提交更改,並且從遠端儲存庫中提取新的更改以保持本地副本最新。當協作者準備好共享他們的更改時,他們可以將這些更改推送到可公開訪問的儲存庫,供其他協作者訪問。一旦公共儲存庫驗證了這個提交可以應用於被推送到的分支,就會為公共儲存庫建立在本地儲存庫中建立和儲存的相同物件,並更新該儲存庫以供所有協作者訪問。

640?wx_fmt=png

要初始化本地 Git 儲存庫,請執行 "Git init" 命令。這將在本地檔案系統上建立一個新初始化的儲存庫,在當前工作目錄中建立一個 .git 目錄。.git 目錄是根 "工作目錄" 的子目錄,並作為實際的本地儲存庫,包含各種配置檔案,物件資料庫,分支的引用指標以及可在專案生命週期的各個點執行的其他指令碼。一旦你對檔案進行了修改,就會建立另一個重要檔案,Git index,位於 .git/index 下。Git index 檔案是工作目錄和本地儲存庫之間的暫存區域,在要提交的一個或多個檔案中暫存特定的更改。


640?wx_fmt=png

值得注意的缺點


Git 使用工具包編寫的設計理念與 Linux 社群中使用和構建的命令列工具相同。雖然工具包設計為使用者提供了 Git 大量功能更細粒度,更低級別的訪問,但由於大量的命令可能對許多不熟悉命令列工具的人或其他 VCS 使用者不直觀,所以新使用者的學習曲線很陡峭。Git 還缺乏連結和構建到其他服務和應用的能力。許多在 Git 上構建或正在構建工具的應用程式開發者抱怨缺乏可連線的庫。Git 的二進位制檔案是不可重入的,這意味著它不能在執行過程中被中斷,之後安全地再次被呼叫。這會強制一些使用該二進位制檔案的應用程式或 Web 服務執行並呼叫該二進位制檔案後,在再次呼叫它之前等待其完全執行,影響應用程式的速度。有幾個專案正在努力彌補這種缺乏可連線庫的情況,其中最著名的是 libgit2,一個 Git 的跨平臺可連線庫實現。

Git 的另一些問題是它無法處理大檔案或者大量的檔案。如果你的專案包含很多非文字檔案,比如影象,那麼經常地更新 Git 將變得非常慢,使得最大的實際儲存庫大小隻有幾 GB。


640?wx_fmt=png

最後


Git 的設計幾乎完全符合了 Linus 和 Linux 團隊所尋找的需求。它滿足了 Linus 描述的 VCS 的每個核心需求,並且在使用時儘可能優雅且簡單地做到儘可能高效。雖然 Git 存在一些小問題,但它的設計非常好,並且將在未來的許多年內繼續成為 VCS 的首選。

原文:https://medium.com/@willhayjr/the-architecture-and-history-of-git-a-distributed-version-control-system-62b17dd37742

本文為 CSDN 翻譯,如需轉載,請註明來源出處。

 熱 文 推 薦 

☞ AWS 開戰 MongoDB!

☞ 微信小程式 731 天

☞ 《請不要回應外星人2019》

☞ 剛剛!程式設計師集體榮獲2個冠軍,這份2018 IT報告還說這些!

☞ 程式碼“大換血”,以太坊能耗將減少99%背後的故事

☞ “微信之父”張小龍:我沒去過龍泉寺!

☞ Spark+Alluxio效能調優十大技巧

☞ 春運搶票靠加速包?試試這個Python開源專案吧


  

print_r('點個贊吧!');
var_dump('點個贊吧!');
NSLog(@"點個贊吧!");
System.out.println("點個贊吧!");
console.log("點個贊吧!");
print("點個贊吧!");
printf("點個贊吧!\n");
cout << "點個贊吧!" << endl;
Console.WriteLine("點個贊吧!");
fmt.Println("點個贊吧!");
Response.Write("點個贊吧!");
alert("點個贊吧!")
echo "點個贊吧!"

640?wx_fmt=gif點選“閱讀原文”,開啟 CSDN App 閱讀更貼心!


640?wx_fmt=png 喜歡就點選“好看”吧!