Git簡介之工作原理雜談

來源:互聯網
上載者:User

自從認識Git開始,就一直非常佩服這個軟體,一直想寫點東西來把自己所體會到的記錄下來。Git是由Linux Kernal的創始人Linus設計並發布的一個版本控制軟體,乍一看是愚蠢的設計,實際上是天才的傑作,真可謂是大智若愚。我們都知道傳統的版本控制軟體有CVS,SVN等,但Git跟同源軟體相比能脫穎而出並青出於藍,完全得意於它“大智若愚”的模型設計。

首先想說一下Git模型設計的一些基本概念:Git設計了幾種物件模型,在每種物件模型中,主要包含了對象的size,type和content。Git中包含的對象非常簡單,主要為以下三種:
1. blob: is used to store file data - it is generally a file
2. tree: is basically like a directory - it references a bunch of other trees and/or blobs
3. commit: points to a single tree, marking it as what the project looked like at a certain point in time
(optional)4. tag: The tag object is a way to mark a specific commit as special in some way.

以我們常用的源碼管理為例子,blob對象即項目中的所有實體檔案,包括原始碼、圖片資源、xml配置資訊等等等等的內容,特彆強調它記錄的僅僅是檔案內容,而關於此檔案所在目錄、名字大小等資訊統統記錄在關聯它的tree對象上。我們每次提交,都會產生一個commit對象,並更新有改動的檔案所關聯的所有tree對象,tree除了管理blob還可以管理tree本身。所以,眾多tree對象一起記錄了包含整個項目所有blob對象的資訊,並形成了一個個的DAG(有向非循環圖),以至於在任何時間點任何情況下,通過commit對象關聯的唯一根節點tree,都可以遍曆找出整個項目在這次commit狀態下的全部檔案。

引用一段Git權威書籍的原文:

Git design split file name and content- file name saved in tree- file content saved in blob- so the same blob can stands for multi files with multi namesGit objects are immutable, that is, they cannot ever be changed.- There are references which also stored in Git. - Unlike the objects, references can constantly change.


那麼Git為什麼能夠成為同類軟體中的佼佼者?只是因為這簡潔的幾種object定義嗎?
筆者理解是:傳統版本控制軟體CVS,SVN,在檔案被修改之後提交,提交之後再修改再提交,它們只記錄檔案之間的差異狀態,也就是為一個檔案從建立之初就只有一個副本,以後所有的改變都是通過記錄的差異從原始的副本計算得來。而Git的設計理念是,任何檔案,只要有任何改動,哪怕是一個位元組也好,都會重新建立一個副本(即之前提到的blob)對象,若一個檔案被修改了4次就會有4個副本,每一個都是獨立的,都與每次提交產生commit對象所管理。乍一看Git的這種設計非常消耗硬碟,確實是這樣,貌似非常愚鈍!但當今的電腦時代,硬碟的低廉和容量的飛速擴大,讓這磁碟空間的消耗變得越來越微不足道。Git的設計者Linus就充分利用這一點,犧牲了磁碟空間,換取
了無限控制上的靈活和管理的高效。這就是筆者之前提到的“大智若愚”

下面通過一個實際的例子來介紹Git的工作原理:
假設我們的項目裡目錄結構是這樣子的:

- src- java- Hello.java- resource.xml- lib- rt.jar- run.bat


1.當我們使用git init建立repository並第一次提交整個項目之後,會形成4個blog對象分別儲存Hello.java,resource.xml, rt.jar和run.bat。並形成一個commit對象和四個tree對象(分別代表src、java和lib和整個項目根目錄root)。
此時Git裡的預設HEAD即指向最近一次提交的tree對象。通過checkout HEAD,可以把最近一次提交的所有檔案都找出來。(實際上這所有的對象都儲存在隱藏目錄.git/objects裡面)

2.現在我們唯獨只修改Hello.java,並進行第二次提交,那麼Git會產生一個新的blob對象記錄修改後的Hello.java,並產生一個新的commit對象。由於blob只記錄檔案內容,其他檔案資訊、目錄結構等都由tree對象記錄,所以Hello.java改變導致代表java目錄的tree發生了改變,父目錄src代表的tree對象也發生了改變,根目錄同理,所以這次提交還會產生三個新的tree對象(代表新的src和新的java和新的項目根目錄root)

3.當有另外一個開發人員希望得到項目的第一次提交狀態的話,只需要提供第一提交的commit對象的key,它記錄的僅僅是第一提交的root tree,這個root tree會找到舊的src tree對象,java tree對象和並非改變過的lib tree對象,並通過它們找回它們所管理的所有blog對象。至此,第一次提交時的整個項目就被checkout 出來了。我們可以給某次commit對象起便於記憶的別名,這也就形成了我們所熟悉的tag和branch的概念。下次checkout提供別名就可以了。

這樣設計的優勢是什麼呢?筆者的理解是,對於大型項目來說,建立分支是很常見的。Git的整套模型設計賦予了開發人員最大的靈活性來任意建立分支並在自己的分支上開發。到一定時間需要merge到主乾的時候,除非是對同一個檔案內容的修改需要處理衝突(合并兩個blob對象)之外,其餘部分只是在merge兩棵tree,把有向非循環圖tree中對blob的指標和少量檔案基本資料更新,形成一棵新的tree,如此而已!在實際項目開發中,畢竟建立分支的不同開發都是在分支上開發少量的新功能,大部分內容與主幹並無區別,所以merge成新的tree的時候,對毫無改變的blob對象,merge前後的tree都依然指向它們,對於各自分支的修改檔案,分別merge到主幹上也只是更新了少量的tree和blob而已。(如果對資料結構還有些基礎的話,不妨試著畫一畫,你會發現把兩個有向非循環圖合并是如此之簡單高效)

最後附上一些常用的Git命令供實驗和參考:(推薦一本介紹Git的書《Pro Git》,在學習Git的過程中,其實也是在學習如何根據衍化設計出高效實用的軟體的過程)

git cat-file -tgit ls-treegit showgit addgit commitgit commit -a git checkout HEADgit hash-object <file_name>git show -s --pretty=rawfind .git/objects/ -type fgit branch <branch_name>git branch - list all branchesgit branch -D <branch_name> (- delete a branch)git merge <branch_name> (- merge branch with name indicated into active branch)git checkbox <branch_name> - switch active branch, default is mastergit archivegit tag <name> (- this will indicated the lastest commit hash value, also called lightweight tag)git tag -a <name> (- will add a tag object, saved in .git/objects, cat-file will return "tag" type)


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.