幾乎每一種版本控制系統都支持分支。使用分支意味着你能夠從開發主線上分離開來,而後不影響主線的同時繼續工做。在不少版本控制系統中,這是個昂貴的過程,經常須要建立一個源代碼目錄的完整副本,對大型項目來講會花費很長時間。git
做爲優越的版本控制系統,Git 對分支的管理是極其輕便易用的。本文具體說明Git是如何進行分支管理的,如分支的建立、查看、切換、刪除等,以及分支的合併及衝突解決。分支對於多人協做是及其重要,內容較多,慢慢來~工具
有人把 Git 的分支模型稱爲「必殺技特性」,而正是由於它,將 Git 從版本控制系統家族裏區分出來。Git 有何特別之處呢?Git 的分支可謂是難以置信的輕量級,它的新建操做幾乎能夠在瞬間完成,而且在不一樣分支間切換起來也差很少同樣快。和許多其餘版本控制系統不一樣,Git 鼓勵在工做流程中頻繁使用分支與合併,哪怕一天以內進行許屢次都沒有關係。理解分支的概念並熟練運用後,你纔會意識到爲何 Git 是一個如此強大而獨特的工具,並今後真正改變你的開發方式。學習
分支的理念就是分身,就像孫悟空拔出猴毛變出不少跟本身如出一轍的猴子,而後每一個猴子(程序猿)作本身的事情互不干涉,等到全部猴子作完以後,猴子集合來合併勞動成果,而後悟空就把那些猴子猴孫門通通收回了。spa
其餘版本控制系統如SVN等都有分支管理,可是用過以後你會發現,這些版本控制系統建立和切換分支比蝸牛還慢,簡直讓人沒法忍受,結果分支功能成了擺設,你們都不去用。但Git的分支是不同凡響的,不管建立、切換和刪除分支,Git在1秒鐘以內就能完成!不管你的版本庫是1個文件仍是1萬個文件。版本控制
爲了理解 Git 分支的實現方式,咱們須要回顧一下 Git 是如何儲存數據的。或許你還記得第一章的內容,Git 保存的不是文件差別或者變化量,而只是一系列文件快照。這就使得 Git分支建立及切換等操做就如拔毛同樣迅速。指針
在本地倉庫操做一章中,可知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。只是目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也愈來愈長。code
當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev (切換分支),就表示當前分支在dev上:blog
從如今開始,對工做區的修改和提交就是針對dev分支了,好比新提交一次後,dev指針往前移動一步,而master指針不變:開發
有了上述的理解,咱們開始具體的操做實戰,首先來了解一下幾個Git 命令:rem
git branch 查看分支
git branch <branch name> 建立分支
git checkout <branch name> 切換分支
git checkout -b <branch name> 建立分支並切換
可以使用以前章節本地倉庫操做使用過的git庫,查看當前git庫分支,因爲沒有其餘分支操做,僅有一master分支; git branch dev 建立一dev分支,並查看,可見此時有兩個分支,但指向還是master
;
切換分支至 dev, git checkout dev ,可見此時指向是 dev 分支了; 建立及切換可併爲一步,如咱們建立並指向 一 bug 分支 git checkout -b bug ,目前咱們有三條分支,且指向是新建的bug分支了
;
在操做過程當中,是否是很迅速,即便git庫很龐大也是如此,正如前文所言,git 分支管理是如此的輕便易用,當你切換分支後,就不用擔憂當前的操做會影響他人及主線了。
Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:
合併分支命令以下:
git merge <branch name> 合併某分支至當前分支
暫不考慮衝突的狀況,來實際操做下 merge 及刪除分支。
在文件夾下 init git庫,添加 a.txt,add並commit;建立 dev 分支並切換至該分支,在dev分支上新建文件,如 b.txt, add 並 commit;切換至 master 分支並 merge dev分支
git merge命令用於合併指定分支到當前分支。合併後,再查看文件夾,就能夠看到,和dev分支的最新提交是徹底同樣的。
注意到上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。
固然,也不是每次合併都能Fast-forward,其餘方式的合併會後續介紹。
一樣的,操做同一文件內容的修改,且未產生衝突的狀況。如 dev 分支上,修改 a.txt, 如僅在該文件追加記錄內容,切換master分支併合並, 以下:
若是dev分支變更,master分支也有對應變更,則可能引起衝突;此時,若是仍使用上述方式merge,則會報錯,具體的解決衝突方式將於後續介紹。
正如上文所言,Git 是鼓勵使用多分支的,就會有不少分支的存在,然而多餘分支管理上必然會比較雜亂;故,需刪除無用的分支,刪除分支命令以下:
git branch -d <branch name> 刪除分支
一樣的,操做刪除dev分支,以下:
若dev分支未merge至master,則會報警以下:
可見 "-D" 能夠無視merge,刪除分支。
以前的merge即合併分支章節,有說起衝突;如今,來具體說明下衝突的產生及 Git是如何解決衝突的。
首先,瞭解下衝突的產生,如在時間節點a,從master上分支出feature1分支,feature1分支上對文件f作了更新,此時準備merge至master;如master分支在 a時間節點後已對文件f作了更新並提交;此時,就可能產生衝突。
這種狀況下,Git沒法執行「快速合併」,只能試圖把各自的修改合併起來,但這種合併就可能會有衝突。
簡單模擬下該狀況: master分支 1.txt 文件內容爲 "aaa"; 此時,分支出feature1,更改 1.txt 內容爲"feature" 並commit;切換至master分支,更改 1.txt 內容爲 "bbb";
此時,如果執行快速merge,即master下 git merge feature1
會報錯如上,且告知,1.txt文件存在衝突,必須解決衝突後再提交。git status也能夠告訴咱們衝突的文件。手動打開 1.txt,可見以下:
Git用<<<<<<<,=======,>>>>>>>標記出不一樣分支的內容,咱們修改以下後保存並提交:
此時,master及feature1就變成了以下圖(綠線表示已合併)
git log 可看出帶上了feature1分支的提交,以及最後一次的手動解決衝突
遠程分支的操做其實和本地大同小異,只是須要指向遠程。
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,而且,遠程倉庫的默認名稱是origin。
要查看遠程庫的信息,可用git remote, git remote -v顯示更詳細的信息:
git remote 顯示遠程庫信息
上面顯示了能夠抓取和推送的origin的地址。若是沒有推送權限,就看不到push的地址。
至於遠程推送,以前可知用 git push origin master , 如若推送遠程其餘的分支,如 git push origin dev, 更更名稱便可。
遠程獲取一樣如此,如: git pull origin dev。
遠程分支push,可能會產生衝突,此時如何解決?其實同分支衝突解決雷同,只須多加一步,即首先 pull 最新的遠程分支,再merge,若仍有衝突,則須手動解決衝突後再次 push便可。
其實以前的的章節已說起了一些關鍵分支的策略,即 master 分支、dev分支 及 bug、feature分支等。
一般應用於團隊的分支管理策略以下:
首先,master分支應該是很是穩定的,基本上僅用來發布新版本;
其次,代碼的coding都在dev分支上;dev分支是不穩定的,到某個時候,好比2.0版本發佈時,再把dev分支合併到master上,在master分支發佈2.0版本;
而後,天然每一個人都有本身的分支,時不時地往dev分支上合併就能夠了。
因此,團隊合做的分支看起來就像這樣: