匿名
尚未登入
登入
DILA Wiki
搜尋
檢視 Pro Git 3.1 分支是什麼 的原始碼
出自DILA Wiki
命名空間
頁面
討論
更多
更多
頁面操作
閱讀
檢視原始碼
歷史
←
Pro Git 3.1 分支是什麼
由於下列原因,您沒有權限進行編輯此頁面的動作:
您請求的操作只有這個群組的使用者能使用:
使用者
您可以檢視並複製此頁面的原始碼。
為了理解 Git 分支(branch)的實做方式,我們需要回顧一下 Git 是如何儲存資料的。或許你還記得第一章的內容,Git 保存的不是檔案差異或者變化量,而只是一系列檔案快照。 在 Git 中提交時,會保存一個提交(commit)物件,它包含一個指向暫存內容快照的指標,作者和相關附屬資訊,以及一定數量(也可能沒有)指向該提交物件直接祖先的指標:第一次提交是沒有直接祖先的,普通提交有一個祖先,由兩個或多個分支合併產生的提交則有多個祖先。 為直觀起見,我們假設在工作目錄中有三個檔,準備將它們暫存後提交。暫存操作會對每一個檔案計算校驗和(checksum, 即第一章中提到的 SHA-1 雜湊字串),然後把當前版本的檔案快照保存到 Git 倉庫中(Git 使用 blob 類型的物件儲存這些快照),並將校驗和加入暫存區域: <syntaxhighlight lang="XML"> $ git add README test.rb LICENSE2 $ git commit -m 'initial commit of my project' </syntaxhighlight> 當使用 git commit 新建一個提交物件前,Git 會先計算每一個子目錄(本例中就是專案根目錄)的校驗和,然後在 Git 倉庫中將這些目錄保存為樹(tree)物件。之後 Git 創建的提交物件,除了包含相關提交資訊以外,還包含著指向這個樹物件(專案根目錄)的指標,如此它就可以在將來需要的時候,重現此次快照的內容了。 現在,Git 倉庫中有五個物件:三個表示檔案快照內容的 blob 物件;一個記錄著目錄樹內容及其中各個檔對應 blob 物件索引的 tree 物件;以及一個包含指向 tree 物件(根目錄)的索引和其他提交資訊中繼資料(metadata)的 commit 物件。概念上來說,倉庫中的各個物件保存的資料和相互關係看起來如圖 3-1 所示: [[圖片:pro-git-3-1.png]]<br> 圖 3-1. 一次提交後倉庫裡的資料 作些修改後再次提交,那麼這次的提交物件會包含一個指向上次提交物件的指標(譯注:即下圖中的 parent 物件)。兩次提交後,倉庫歷史會變成圖 3-2 的樣子: [[圖片:pro-git-3-2.png]]<br> 圖 3-2. 多次提交後的 Git 物件資料 現在來談分支。Git 中的分支,其實本質上僅僅是個指向 commit 物件的可變指標。Git 會使用 master 作為分支的預設名字。在若干次提交後,你其實已經有了一個指向最後一次提交物件的 master 分支,它在每次提交的時候都會自動向前移動。 [[圖片:pro-git-3-3.png]]<br> 圖 3-3. 指向提交資料歷史的分支 那麼,Git 又是如何創建一個新的分支的呢?答案很簡單,創建一個新的分支指標。比如新建一個 testing 分支,可以使用 git branch 命令: <syntaxhighlight lang="XML"> $ git branch testing </syntaxhighlight> 這會在當前 commit 物件上新建一個分支指標(見圖 3-4)。 [[圖片:pro-git-3-4.png]]<br> 圖 3-4. 多個分支指向提交資料的歷史 那麼,Git 是如何知道你當前在哪個分支上工作的呢?其實答案也很簡單,它保存著一個名為 <b>HEAD</b> 的特別指標。請注意它和你熟知的許多其他版本控制系統(比如 Subversion 或 CVS)裡的 HEAD 概念大不相同。在 Git 中,它是一個<b>指向你正在工作中的本地分支的指標</b>。運行 git branch 命令,僅僅是建立了一個新的分支,但不會自動切換到這個分支中去,所以在這個例子中,我們依然還在 master 分支裡工作(參考圖 3-5)。 [[圖片:pro-git-3-5.png]]<br> 圖 3-5. HEAD 指向當前所在的分支 要切換到其他分支,可以執行 git checkout 命令。我們現在轉換到新建的 testing 分支: <syntaxhighlight lang="XML"> $ git checkout testing </syntaxhighlight> 這樣 HEAD 就指向了 testing 分支(見圖3-6)。 [[圖片:pro-git-3-6.png]]<br> 圖 3-6. HEAD 在你轉換分支時指向新的分支 這樣的實現方式會給我們帶來什麼好處呢?好吧,現在不妨再提交一次: <syntaxhighlight lang="XML"> $ vim test.rb $ git commit -a -m 'made a change' </syntaxhighlight> 圖 3-7 展示了提交後的結果。 [[圖片:pro-git-3-7.png]]<br> 圖 3-7. 每次提交後 HEAD 隨著分支一起向前移動 非常有趣,現在 testing 分支向前移動了一格,而 master 分支仍然指向原先 git checkout 時所在的 commit 物件。現在我們回到 master 分支看看: <syntaxhighlight lang="XML"> $ git checkout master </syntaxhighlight> 圖 3-8 顯示了結果。 [[圖片:pro-git-3-8.png]]<br> 圖 3-8. HEAD 在一次 checkout 之後移動到了另一個分支 這條命令做了兩件事。它把 HEAD 指標移回到 master 分支,並把工作目錄中的檔案換成了 master 分支所指向的快照內容。也就是說,現在開始所做的改動,將始於本專案中一個較老的版本。它的主要作用是將 testing 分支裡作出的修改暫時取消,這樣你就可以向另一個方向進行開發。 我們作些修改後再次提交: <syntaxhighlight lang="XML"> $ vim test.rb $ git commit -a -m 'made other changes' </syntaxhighlight> 現在我們的專案項目提交歷史產生了分叉(如圖 3-9 所示),因為剛才我們創建了一個分支,轉換到其中進行了一些工作,然後又回到原來的主分支進行了另外一些工作。這些改變分別孤立在不同的分支裡:我們可以在不同分支裡反復切換,並在時機成熟時把它們合併到一起。而所有這些工作,僅僅需要 branch 和 checkout 這兩條命令就可以完成。 [[圖片:pro-git-3-9.png]]<br> 圖 3-9. 分叉了的分支歷史 由於 Git 中的分支實際上僅是一個包含所指物件校驗和(40 個字元長度 SHA-1 字串)的檔案,所以創建和銷毀一個分支就變得非常廉價。說白了,新建一個分支就是向一個檔案寫入 41 個位元組(外加一個分行符號)那麼簡單,當然也就很快了。 這和大多數版本控制系統形成了鮮明對比,它們管理分支大多採取備份所有專案檔案到特定目錄的方式,所以根據專案檔案數量和大小不同,可能花費的時間也會有相當大的差別,快則幾秒,慢則數分鐘。而 Git 的實做方法與專案複雜度無關,它永遠可以在幾毫秒的時間內完成分支的創建和切換。同時,因為每次提交時都記錄了祖先資訊(譯注:即 parent 物件),所以以後要合併分支時,尋找恰當的合併基礎(譯注:即共同祖先)的工作其實已經完成了一大半,實現起來非常容易。Git 鼓勵開發者頻繁使用分支,正是因為有著這些特性作保障。 接下來看看,我們為什麼應該頻繁使用分支。
返回到「
Pro Git 3.1 分支是什麼
」。
導覽
導覽
首頁
近期變更
隨機頁面
MediaWiki說明
wiki工具
wiki工具
特殊頁面
頁面工具
頁面工具
使用者頁面工具
更多
連結至此的頁面
相關變更
頁面資訊
頁面日誌