Git分支-分支簡介

源地址:https://git-scm.com/book/zh/ch3-1.htmlhtml

幾乎全部的版本控制系統都以某種形式支持分支。 使用分支意味着你能夠把你的工做從開發主線上分離開來,以避免影響開發主線。 在不少版本控制系統中,這是一個略微低效的過程——經常須要徹底建立一個源代碼目錄的副本。對於大項目來講,這樣的過程會耗費不少時間。git

有人把 Git 的分支模型稱爲它的「必殺技特性」,也正由於這一特性,使得 Git 從衆多版本控制系統中脫穎而出。 爲什麼 Git 的分支模型如此出衆呢? Git 處理分支的方式可謂是難以置信的輕量,建立新分支這一操做幾乎能在瞬間完成,而且在不一樣分支之間的切換操做也是同樣便捷。 與許多其它版本控制系統不一樣,Git 鼓勵在工做流程中頻繁地使用分支與合併,哪怕一天以內進行許屢次。 理解和精通這一特性,你便會意識到 Git 是如此的強大而又獨特,而且今後真正改變你的開發方式。算法

分支簡介

爲了真正理解 Git 處理分支的方式,咱們須要回顧一下 Git 是如何保存數據的。vim

或許你還記得 起步 的內容,Git 保存的不是文件的變化或者差別,而是一系列不一樣時刻的文件快照。spa

在進行提交操做時,Git 會保存一個提交對象(commit object)。知道了 Git 保存數據的方式,咱們能夠很天然的想到——該提交對象會包含一個指向暫存內容快照的指針。 但不只僅是這樣,該提交對象還包含了做者的姓名和郵箱、提交時輸入的信息以及指向它的父對象的指針。首次提交產生的提交對象沒有父對象,普通提交操做產生的提交對象有一個父對象,而由多個分支合併產生的提交對象有多個父對象,版本控制

爲了說得更加形象,咱們假設如今有一個工做目錄,裏面包含了三個將要被暫存和提交的文件。 暫存操做會爲每個文件計算校驗和(使用咱們在 起步 中提到的 SHA-1 哈希算法),而後會把當前版本的文件快照保存到 Git 倉庫中(Git 使用 blob 對象來保存它們),最終將校驗和加入到暫存區域等待提交:指針

 git add README test.rb LICENSE
 git commit -m $$'The initial commit of my project'

當使用 git commit 進行提交操做時,Git 會先計算每個子目錄(本例中只有項目根目錄)的校驗和,而後在 Git 倉庫中這些校驗和保存爲樹對象。 隨後,Git 便會建立一個提交對象,它除了包含上面提到的那些信息外,還包含指向這個樹對象(項目根目錄)的指針。如此一來,Git 就能夠在須要的時候重現這次保存的快照。code

如今,Git 倉庫中有五個對象:三個 blob 對象(保存着文件快照)、一個樹對象(記錄着目錄結構和 blob 對象索引)以及一個提交對象(包含着指向前述樹對象的指針和全部提交信息)。orm

首次提交對象及其樹結構.Figure 3-1. 首次提交對象及其樹結構htm

作些修改後再次提交,那麼此次產生的提交對象會包含一個指向上次提交對象(父對象)的指針。

提交對象及其父對象.Figure 3-2. 提交對象及其父對象

Git 的分支,其實本質上僅僅是指向提交對象的可變指針。 Git 的默認分支名字是 master。 在屢次提交操做以後,你其實已經有一個指向最後那個提交對象的 master 分支。 它會在每次的提交操做中自動向前移動。

NOTE

Git 的 「master」 分支並非一個特殊分支。 它就跟其它分支徹底沒有區別。 之因此幾乎每個倉庫都有 master 分支,是由於 git init 命令默認建立它,而且大多數人都懶得去改動它。

分支及其提交歷史.Figure 3-3. 分支及其提交歷史

分支建立

Git 是怎麼建立新分支的呢? 很簡單,它只是爲你建立了一個能夠移動的新的指針。 好比,建立一個 testing 分支, 你須要使用 git branch 命令:

 git branch testing$

這會在當前所在的提交對象上建立一個指針。

兩個指向相同提交歷史的分支。Figure 3-4. 兩個指向相同提交歷史的分支

那麼,Git 又是怎麼知道當前在哪個分支上呢? 也很簡單,它有一個名爲 HEAD 的特殊指針。 請注意它和許多其它版本控制系統(如 Subversion 或 CVS)裏的 HEAD 概念徹底不一樣。 在 Git 中,它是一個指針,指向當前所在的本地分支(譯註:將 HEAD 想象爲當前分支的別名)。 在本例中,你仍然在master 分支上。 由於 git branch 命令僅僅 建立 一個新分支,並不會自動切換到新分支中去。

HEAD 指向當前所在的分支.Figure 3-5. HEAD 指向當前所在的分支

你能夠簡單地使用 git log 命令查看各個分支當前所指的對象。 提供這一功能的參數是 --decorate

 git log --oneline --decorate


$f30ab (HEAD, master, testing) add feature #32 - ability to add new34ac2 fixed bug #1328 - stack overflow under certain conditions98ca9 initial commit of my project

正如你所見,當前 「master」 和 「testing」 分支均指向校驗和以 f30ab 開頭的提交對象。

分支切換

要切換到一個已存在的分支,你須要使用 git checkout 命令。 咱們如今切換到新建立的 testing 分支去:

 git checkout testing$

這樣 HEAD 就指向 testing 分支了。

HEAD 指向當前所在的分支.Figure 3-6. HEAD 指向當前所在的分支

那麼,這樣的實現方式會給咱們帶來什麼好處呢? 如今不妨再提交一次:

 vim test.rb
 git commit -a -m $$'made a change'

HEAD 分支隨着提交操做自動向前移動.Figure 3-7. HEAD 分支隨着提交操做自動向前移動

如圖所示,你的 testing 分支向前移動了,可是 master 分支卻沒有,它仍然指向運行 git checkout 時所指的對象。 這就有意思了,如今咱們切換回 master 分支看看:

 git checkout master$

檢出時 HEAD 隨之移動.Figure 3-8. 檢出時 HEAD 隨之移動

這條命令作了兩件事。 一是使 HEAD 指回 master 分支,二是將工做目錄恢復成 master 分支所指向的快照內容。 也就是說,你如今作修改的話,項目將始於一個較舊的版本。 本質上來說,這就是忽略testing 分支所作的修改,以便於向另外一個方向進行開發。

NOTE

分支切換會改變你工做目錄中的文件

在切換分支時,必定要注意你工做目錄裏的文件會被改變。 若是是切換到一個較舊的分支,你的工做目錄會恢復到該分支最後一次提交時的樣子。 若是 Git 不能幹淨利落地完成這個任務,它將禁止切換分支。

咱們不妨再稍微作些修改並提交:

 vim test.rb
 git commit -a -m $$'made other changes'

如今,這個項目的提交歷史已經產生了分叉(參見 Figure 3-9)。 由於剛纔你建立了一個新分支,並切換過去進行了一些工做,隨後又切換回 master 分支進行了另一些工做。 上述兩次改動針對的是不一樣分支:你能夠在不一樣分支間不斷地來回切換和工做,並在時機成熟時將它們合併起來。 而全部這些工做,你須要的命令只有 branchcheckout 和 commit

項目分叉歷史.Figure 3-9. 項目分叉歷史

你能夠簡單地使用 git log 命令查看分叉歷史。 運行 git log --oneline --decorate --graph --all ,它會輸出你的提交歷史、各個分支的指向以及項目的分支分叉狀況。

 git log --oneline --decorate --graph --all





$* c2b9e (HEAD, master) made other changes| * 87ab2 (testing) made a change|/* f30ab add feature #32 - ability to add new formats to the* 34ac2 fixed bug #1328 - stack overflow under certain conditions* 98ca9 initial commit of my project

因爲 Git 的分支實質上僅是包含所指對象校驗和(長度爲 40 的 SHA-1 值字符串)的文件,因此它的建立和銷燬都異常高效。 建立一個新分支就像是往一個文件中寫入 41 個字節(40 個字符和 1 個換行符),如此的簡單能不快嗎?

這與過去大多數版本控制系統造成了鮮明的對比,它們在建立分支時,將全部的項目文件都複製一遍,並保存到一個特定的目錄。 完成這樣繁瑣的過程一般須要好幾秒鐘,有時甚至須要好幾分鐘。所需時間的長短,徹底取決於項目的規模。而在 Git 中,任何規模的項目都能在瞬間建立新分支。 同時,因爲每次提交都會記錄父對象,因此尋找恰當的合併基礎(譯註:即共同祖先)也是一樣的簡單和高效。 這些高效的特性使得 Git 鼓勵開發人員頻繁地建立和使用分支。

接下來,讓咱們看看爲何你應該這麼作?

相關文章
相關標籤/搜索