Git算不算程序員的必備技能?
每天與你分享 IT好書 技術幹貨 職場知識
參與文末話題討論,每日贈送異步圖書。
——異步小編
Git的背後有著一個非常精彩的成功故事。2005年4月,Linus Torvalds因不滿當時任何一個可用的開源版本控制系統,就親自著手實現了Git。
時至今日,如果我們在Google中搜索“git version control”這幾個關鍵詞,都會看到數以百萬計的返回結果。Git已經儼然成為了新型開源項目的一個標準。許多大型的開源項目都已經或正在計劃遷移到Git上來。Git算不算程序員的必備技能?答案是肯定的。
為什麽要用Git?
站在巨人的肩膀上,我們要特別感謝Linus Torvalds、Junio C. Hamano以及Git項目的眾多提交者,是他們給開發者社區帶來了這個奇妙的工具。
Git允許我們利用分支來開展工作:在一個由多個開發者並行協作的項目中,開發者各自會有很多不同的開發路線。Git的優勢在於,它提供了一整套針對開發鏈的重新整合工具,以便我們對其進行合並、變基和撿取等操作。
工作流上的靈活性:Git非常靈活。不但單一開發者可以用它,敏捷團隊也可以找到使用它工作的合適方法,甚至一個由眾多開發者在不同的工作地點參與的大型國際項目也可以用它開發出一個很好的工作流。
適合奉獻合作:大多數開源項目所依靠的都是開發者的無私奉獻。因此,讓這種無私奉獻的方式盡可能地簡單化是一件非常重要的事。而這在一個集中式的版本控制系統中通常是很難做到的,因為我們不可能讓所有人都有權限去寫版本庫。但如果我們使用Git,那麽每個人都先可以克隆一個獨立的工作版本庫,然後再對其進行後續的改動。
高性能:Git在處理擁有許多文件且歷史悠久的項目時速度也依然是非常快的。例如,使用Git將Linux內核源碼的當前版本切換到6年前的舊版本時,在一臺MacBook Air上所需的時間不到1分鐘。考慮這兩個版本之間有著超過200000次的提交和40000個更改文件,這已經足以讓人印象深刻了。
強大的抗故障和抗攻擊能力:由於項目歷史被分散存儲在多個分布式版本庫中,因此數據嚴重流失的可能性不大。再加上版本庫中有著巧妙簡單的數據結構,這確保了其中的數據即使在遙遠的未來也仍然會被正確地解釋。而且,它還使用了統一的加密校驗,這使得攻擊者難以對版本庫進行篡改。
離線開發與多點開發:分布式的體系結構可以使得離線開發或者邊旅行邊開發的方式變得非常容易。而且該結構在多點開發模式下,我們既不需要設置中央服務器,也不需要固定的網絡連接。
強大的開源社區:除官方提供的詳細文檔外,你還可以在該社區找到無數相關的手冊、論壇、維基網站等,另外還有各種工具生態系統、托管平臺、出版物、服務以及針對各個開發環境的插件,整個社區都正在茁壯成長。
可擴展性:Git為用戶提供了許多實用命令,其中包括了能使我們更便於直接訪問其遠程版本庫的命令。這可以讓Git變得非常靈活,這種靈活性將允許其各種獨立應用提供比默認的Git版本更為強大的功能。
為什麽要用工作流
Git非常靈活。可為多種不同的角色所用,從偶爾需要版本化少量shell腳本的單一系統管理員,到Linux內核項目中的上百個開發人員,一切皆有可能。當然,這種靈活性不是沒有代價的。在開始用Git來開展工作之前,你還必須要做一組決定。例如以下幾種。
Git中固然已經是分布式版本庫。但你是真的打算只在本地工作,還是更願意建立一個中央版本庫?
Git支持push和pull兩種數據傳輸類型,但我們需要同時使用它們嗎?如果讓你選,你會選哪一個?為什麽不是另一個?
分支與合並是Git中兩個強大的功能。但是,我們應該開多少個分支呢?是根據每個軟件功能來開?還是針對每個發行版來開?還是只該有一個分支?
為了便於入門,下面我們來總結一下工作流及其作用。
工作流指的是相關項目的日常操作規程。
工作流會給出具體的步驟。
工作流會顯示必要的命令和選項。
工作流非常適用於密切的團隊合作,而目前的這些現代軟件項目通常就出自這樣的合作。
一些工作流可能並不是目標問題唯一正確的解決方案,但它們是一個很好的起點,我們可以從中為自己的項目開發出高效的工作流。
我們之所以會重點介紹商業項目中敏捷開發團隊的工作,是因為我們相信目前許多專業開發者(包括作者)都處於這樣的工作環境中。當然,這裏並不包括那些具有特殊要求的大型項目,因為這些項目通常有著很誇張的工作流,而且我們相信這些也不是大多數開發者會感興趣的項目。另外,這裏也不包括那些開源項目的開發,雖然這些項目也可以用Git規劃出一個很有意思的工作流。
分布式版本控制,有什麽過人之處
在具體探討分布式版本控制的概念之前,讓我們先來快速回顧一下傳統的集中式版本控制架構。
圖1.1中所顯示的就是一個集中式版本控制系統(例如CVS或Subversion)的典型布局。每個開發者都在他或她自己的計算機上有一個包含所有項目文件的工作目錄(即工作區)。當該開發者在本地做了修改之後,他或她就會定期將修改提交給某臺中央服務器。然後,開發者在執行更新操作的同時也會從該服務器上撿取出其他開發者所做的修改。這臺中央服務器上存儲著這些文件(即版本庫)的當前版本和歷史版本。因此,這些被並行開發的分支,以及各種被命名(標記)的版本都將會被集中管理。
圖1.1 集中式版本控制
而在分布式版本控制系統(見圖1.2)中,開發者環境與服務器環境之間是沒有分隔的。每一個開發者都同時擁有一個用於當前文件操作的工作區與一個用於存儲該項目所有版本、分支以及標簽的本地版本庫(我們稱其為一份克隆)。每個開發者的修改都會被載入成一次次的新版本提交(commit), 首先提交到其本地版本庫中。然後,其他開發者就會立即看到新的版本。通過推送(push)和拉回(pull)命令,我們可以將這些修改從一個版本庫傳送到另一個版本庫中。這樣一來,從技術上來看,這裏所有的版本庫在分布式架構上的地位是同等的。因此從理論上來講,我們不再需要借助服務器,就可以將某一臺開發工作機上所做的所有修改直接傳送給另一開發工作機。當然在具體實踐中,Git中的服務器版本庫也扮演了重要的角色,例如以下這些特型版本庫。
圖1.2 分布式版本控制
項目版本庫(blessed repository):該版本庫主要用於存儲由“官方”創建並發行的版本。
共享版本庫(shared repository):該版本庫主要用於開發團隊內人員之間的文件交換。在小型項目中,項目版本庫本身就可以勝任這一角色了。但在多點開發的條件下,我們可能就會需要幾個這樣的專用版本庫。
工作流版本庫(workflow repository):工作流版本庫通常只用於填充那些代表工作流中某種特定進展狀態的修改,例如審核通過後的狀態等。
派生版本庫(fork repository):該版本庫主要用於從開發主線分離出某部分內容(例如,分離出那些開發耗時較長,不適合在一個普通發布周期中完成的內容),或者隔離出可能永遠不會被包含在主線中的、用於實驗的那部分開發進展。
下面,我們再來看看分布式系統相對於集中式的優點有哪些。
高性能:幾乎所有的操作都無需進行網絡訪問,均可直接在本地執行。
高效的工作方式:開發者可通過多個本地分支在不同任務之間進行快速切換。
離線功能:開發者可以在沒有服務器連接的情況下執行提交、創建分支、版本標簽等操作。之後再將其上傳服務器。
靈活的開發進程:我們可以在團隊和公司中為其他部門建立專用的版本庫,例如為方便與測試人員交流而建的版本庫。這樣相關修改就很容易發布,因為只是特定版本庫上的一次推送。
備份作用:由於每個開發者都持有一份擁有完整歷史版本的版本庫副本,所以因服務器故障而導致數據丟失的可能性是微乎其微的。
可維護性:對於那些難以對付的重構工作,我們可以在將成功傳送給其原始版本庫之前,先在該版本庫的副本上嘗試一下。
版本庫,分布式的基礎所在
其實,版本庫本質上就是一個高效的數據存儲結構而已,由以下部分組成。
文件(即blob):這裏既包含了文本也包含了二進制數據,這些數據將不以文件名的形式被保存。
目錄(即Tree):目錄中保存的是與文件名相關聯的內容,其中也會包含其他目錄。
版本(即commit):每一個版本所定義的都是相應目錄的某個可恢復的狀態。每當我們創建一個新的版本時,其作者、時間、註釋以及其之前的版本都將會被保存下來。
對於所有的數據,它們都會被計算成一個十六進制散列值(例如像1632acb65b01 c6b621d6e1105205773931bb1a41這樣的值)。這個散列值將會被用作相關對象的引用,以及日後恢復數據時所需的鍵值(見圖1.3)。
圖1.3 版本庫中的對象存儲
也就是說,一個提交對象的散列值實際上就是它的“版本號”,如果我們持有某一提交的散列值,就可以用它來檢查對應版本是否存在於某一版本庫中。如果存在,我們就可以將其恢復到當前工作區相應的目錄中。如果該版本不存在,我們也可以從其他版本庫中單獨導入(拉回)該提交所引用的全部對象。
接下來,我們來看看采用這種散列值和這種既定的版本庫結構究竟有哪些優勢。
高性能:通過散列值來訪問數據是非常快的。
冗余度——釋放存儲空間:相同的文件內容只需存儲一次即可。
分布式版本號:由於相關散列值是根據文件,作者和日期來計算的,所以版本也可以“離線”產生,不用擔心將來會因此而發生版本沖突。
版本庫間的高效同步:當我們將某一提交從一個版本庫傳遞給另一個版本庫時,只需要傳送那些目標版本庫中不存在的對象即可。而正是因為有了散列值的幫助,我們才能很快地判斷相關對象是否已經存在。
數據完整性:由於散列值是根據數據的內容來計算的,所以我們可以隨時通過Git來查看某一散列值是否與相關數據匹配。以檢測該數據上可能的意外變化或惡意操作。
自動重命名檢測:被重命名的文件可以被自動檢測到,因為根據該文件內容計算出的散列值並沒有發生變化。也正因為如此,Git中並沒有專用的重命名命令,只需移動命令即可。
分支的創建與合並很簡單
對於大多數版本控制系統來說,分支的創建與合並通常會因其特殊性而被認為是高級拓展操作。但由於Git最初就是為了方便那些散落在世界各地的Linux內核開發者而創建的,合並多方努力的結果一直都是其面臨的最大挑戰之一,所以Git的設計目標之一就是要讓分支的創建與合並操作變得盡可能地簡單且安全。
在下面的圖1.4中,我們向你展示了開發者是如何通過創建分支的方式來進行並行開發的。圖中的每一個點都代表了該項目的一個版本(即commit)。而由於在Git中,我們只能對整個項目進行版本化,所以每個點同時也代表了屬於同一版本的各個文件。
圖1.4 因開發者的並行開發而出現的分支創建操作
如上所示,圖中兩位開發者的起點是同一個版本。之後兩人各自做了修改,並提交了修改。這時候,對於這兩位開發者各自的版本庫來說,該項目已經有了兩個不同的版本。也就是說,他們在這裏創建了兩個分支。接下來,如果其中一個開發者想要導入另一個人的修改,他/她就可以用Git來進行版本合並。如果合並成功了,Git就會創建一個合並提交,其中會包含兩位開發者所做的修改。這時如果另一位開發者也取回了這一提交,兩位開發者的項目就又回到了同一個版本。
在上面的例子中,分支的創建是非計劃性的,其原因僅僅是兩個開發者在並行開發同一個軟件罷了。在Git中,我們當然也可以開啟有針對性的分支,即顯式地創建一個分支(見圖1.5)。顯式分支通常主要用於協調某一種功能性的並行開發。
圖1.5 針對不同任務的顯式分支
版本庫在執行拉回和推送操作時,可以具體指定其針對的是哪一些分支。當然,除了這些簡單的分支創建和合並處理外,我們也可以對分支執行以下動作。
移植分支:我們可以直接將某一分支中的提交轉移到另一個版本庫中。
只傳送特定修改:我們可以將某一分支中的某一次或某幾次提交直接復制到另一個分支中。這就是所謂的撿取處理。
清理歷史:我們可以對分支歷史進行改造、排序和刪除。這有利於為該項目建立更好的歷史文檔。我們稱這種處理為交互式重訂(interactive rebasing)。
另外,如果你是一個繁忙的項目管理者,還在猶豫不決是否要采用Git
該讀什麽書?
《Git高手之路》
Jakub Nar?bski 著
點擊封面購買紙書
本書面向所有的Git用戶,全面細致地向讀者介紹有關Git的各項實用技巧,充分發掘它的潛力,更好地實現項目版本管理。學習本書,可以幫助讀者更好地運用Git,提升軟件開發效率。
本書作者Jakub Nar?bski自Git誕生之初就參與了Git的開發工作。他是gitweb子系統(Git原始Web界面)的主要貢獻者之一,是非官方的gitweb維護者。
《Git學習指南》
【德】René Prei?el(普萊貝爾), Bj?rn Stachmann(斯拉赫曼) 著
點擊封面購買紙書
Git 是當今最流行的版本控制系統。本書並不偏重理論介紹,也不面面俱到,而是一本學習Git的實用指南。本書首先介紹了Git 的基礎知識,然後關註於敏捷開發,並給出工作流展示了解決現實問題所需的命令和選項。
《Git版本控制管理(第2版)》
【美】Jon Loeliger , Matthew McCullough 著
點擊封面購買紙書
市面上絕無僅有的Git圖書 全面剖析Git的用法 同時涵蓋GitHub
本書可以讓讀者迅速上手Git,用它來跟蹤、分支、合並和管理代碼變更。本書通過一系列步驟式教程,引導讀者迅速掌握從Git基礎知識到高級使用技巧在內的所有知識,並提供友好而嚴謹的建議,以幫助讀者熟悉Git的許多功能。
本書在上一版的基礎之上進行了全面更新,包含了操作樹的技巧,全面覆蓋了reflog和stash的用法,還全面介紹了GitHub倉庫。一旦你掌握了Git系統的靈活性之後,你可以以近乎無限的各種方式來管理代碼開發,而本書則會告訴你怎麽來做。
今日互動
你用過Git嗎?截止時間4月29日17時,留言+轉發本活動到朋友圈,小編將抽獎選出5名讀者贈送e讀版100元異步社區代金券一張,(留言點贊最多的自動獲得一張)。
推薦閱讀
2018年4月新書書單
異步圖書最全Python書單
一份程序員必備的算法書單
第一本Python神經網絡編程圖書
長按二維碼,可以關註我們喲
每天與你分享IT好文。
在“異步圖書”後臺回復“關註”,即可免費獲得2000門在線視頻課程;推薦朋友關註根據提示獲取贈書鏈接,免費得異步e讀版圖書一本。趕緊來參加哦!
掃一掃上方二維碼,回復“關註”參與活動!
點擊閱讀原文,直接購買《Git高手指南》
閱讀原文
Git算不算程序員的必備技能?