在git中,分支指的是從主線上分離出來進(jìn)行另外的操作,既不影響主線,主線又可以繼續(xù)干它的事,它可用來解決臨時需求;當(dāng)分支做完事后可合并到主線上,而分支的任務(wù)完成可以刪掉了。
本教程操作環(huán)境:Windows7系統(tǒng)、Git2.30.0版、Dell G3電腦。
git的分支是什么
? ? ? ? 顧名思義,分支就是從主線上分離出來進(jìn)行另外的操作,而又不影響主線,主線又可以繼續(xù)干它的事,是不是有點(diǎn)像線程,最后分支做完事后合并到主線上而分支的任務(wù)完成可以刪掉了。這樣是不是很方便,主線繼續(xù)做它的事,分支用來解決臨時需求,二者互不相干。
? ? ? ? git的分支功能特別的強(qiáng)大,它不需要將所有數(shù)據(jù)進(jìn)行復(fù)制,只要重新創(chuàng)建一個分支的指針指向你需要從哪里開始創(chuàng)建分支的提交對象(commit),然后進(jìn)行修改再提交,那么新分支的指針就會指向你最新提交的這個commit對象,而原來分支的指針則指向你原來開發(fā)的位置,當(dāng)你在哪個分支開發(fā),HEAD就指向那個分支的最新提交對象commt。沒弄清楚沒關(guān)系,先有這么一個概念,后面慢慢就會弄清的。
分支的新建與合并
? ? ? ? 我們可以用命令git branch來查看我們的git倉庫有幾個分支,而我們目前工作處于那個分支,前面有個*號的就為我們目前所處的分支。我們可以通過命令git branch name來創(chuàng)建分支,而這個分支的指針就指向最新的commit對象,也就和HEAD指向同一對象。我們可以通過命令git checkout name來切換到目的分支,我們默認(rèn)的主分支為master。在分支的創(chuàng)建和切換,其實(shí)只是簡單的創(chuàng)建指針找指針而已,而根據(jù)找到的指針找到所指向的commit對象,然后將工作空間恢復(fù)成該commit對象所指的文件快照讓我們來工作。當(dāng)提交一次,指針就重新指向這個最新提交的對象,特別的簡單。
? ? ? ? 當(dāng)我們建立分支teset之前,只有master一個主分支,如圖一,我們所有的開發(fā)都是在這個分支上,而且HEAD是指向最近一次提交的commit對象c3,c3以前還有兩次提交c1和c2,這時我們通過git branch test創(chuàng)建test分支,如圖二,這時HEAD還是指向master分支最近一次提交的c3,當(dāng)git checkout test切換到test分支后,HEAD就指向test分支的最近一次提交c3,這個時候其實(shí)在.git里面都是指向同樣一份數(shù)據(jù)c3。
? ? ? ? 這個時候,當(dāng)我們在test分支上進(jìn)行了幾次開發(fā)提交了c4和c5兩個版本后,那么test和HEAD都指向test分支的最近一次提交c5,如圖三,而master此時還沒有變化,任然指向的是c3,如果這個時候?qū)est分支合并到master分支,那么git根本不用做什么,只要將master移動,指向c5就可以了,這個過程稱之為Fast-forward快進(jìn)。如果此時test的任務(wù)完成,我們就可以通過git branch -d test將它刪除掉,繼續(xù)在主分支master上進(jìn)行開發(fā)。如果是這樣的話,那么test分支就白建了。
? ? ? ?那么如果此時master分支上又進(jìn)行另外的開發(fā),提交了兩個版本c6和c7,那么此時的master和HEAD指針都指向的是c7,如圖四,可以看出在哪個分支上開發(fā),那么HEAD就指向的是哪個分支上的commit,這個時候合并兩個分支的話,就如下。
? ? ? ? 如圖五,我們先切換到master分支,然后通過git merge test將test分支合并到master分支,這個時候,git就不是簡單的移動指針了,因?yàn)閮蛇叾加虚_發(fā),所以git就要對于兩個分支的最新提交c5和c7還有兩個分支共同的祖先commit對象c3來進(jìn)行一次簡單的三方合并,產(chǎn)生新的文件快照并用新的commit對象c8記錄,這個合并的過程不需要太在意,如果產(chǎn)生了沖突,也就是兩個分支對同一個文件進(jìn)行了修改,那么git就會停下合并操作,讓你處理好沖突后,再提交(c8),然后再進(jìn)行合并。這時master和HEAD都指向c8,但是test是沒有移動的,此時還可以在test上繼續(xù)開發(fā),再合并到master,如果test已經(jīng)沒有利用價值了就可以刪掉了。
本地分支,追蹤分支和遠(yuǎn)程分支
? ? ? ? 這里有三個概念,本地分支就是我們可以通過git branch查看到的分支,也就是我們自己git倉庫所擁有的分支,我們都可以利用。遠(yuǎn)程分支是對遠(yuǎn)程倉庫的分支的索引,它其實(shí)也是本地分支,只是我們無法移動它,必須要在和中心服務(wù)器交互根據(jù)服務(wù)器更新到本地來的代碼移動的,遠(yuǎn)程分支的作用就是我們上次和中心服務(wù)器交互更新得到的最新版本,它也是個指針。追蹤分支比較難理解,它也是一個本地分支,只是它對應(yīng)了一個遠(yuǎn)程分支,如果我們本地的某個分支對應(yīng)了一個特定的遠(yuǎn)程分支,那么它就是追蹤分支,比如我們最初的master分支就是一個追蹤分支,它對應(yīng)遠(yuǎn)程分支origin/master,這里origin是遠(yuǎn)程倉庫名,當(dāng)我們在master分支里執(zhí)行更新(fetch,pull)或是推送(push),在不指定分支的情況下,默認(rèn)就是從origin/master分支更新來或者提交到origin/mster分支。
? ? ? ? 從圖七和圖八很容易看出來,和我們本地創(chuàng)建分支很相似,只是origin/master遠(yuǎn)程分支只有在連接服務(wù)器并更新服務(wù)器代碼到本地后才會移動,如下圖九:
更新遠(yuǎn)程代碼到本地有兩個命令,fetch和pull,fetch是將遠(yuǎn)程代碼更新到本地,但是不會執(zhí)行合并操作,需要自己查看,解決沖突什么的,然后自己再執(zhí)行merge將更新來的代碼合并到我們自己制定的分支,但是pull就將這兩個操作合成了一步,直接更新服務(wù)器代碼更新并合并到到本地指定分支,當(dāng)然遇到?jīng)_突也必須要自己解決。所以我們一般都使用fetch來實(shí)現(xiàn)更新,雖然麻煩了點(diǎn),但是不容易出問題。
? ? ? ? 將本地代碼推送到遠(yuǎn)程倉庫,也就是中心服務(wù)器,一般我們推送數(shù)據(jù)都是git push origin master:master,這里指定遠(yuǎn)程倉庫名,本地分支名和遠(yuǎn)端分支,也就是將我們本地master分支的數(shù)據(jù)推送到遠(yuǎn)程倉庫origin的master分支。如果本地的master分支是追蹤分支,那么在不指定的情況下,它會自己找到遠(yuǎn)程倉庫中對應(yīng)的分支來推送數(shù)據(jù)。或者我們直接進(jìn)行g(shù)it push origin操作,只指定遠(yuǎn)程倉庫名,那么git會根據(jù)我們目前所在分支和它所對應(yīng)的遠(yuǎn)程倉庫的分支來實(shí)現(xiàn)數(shù)據(jù)推送,前提是我們目前所在分支必須是追蹤分支。當(dāng)然如果是git push origin :master,這里本地分支名是空的,這個操作就是將空分支推送到遠(yuǎn)程倉庫的master分支,結(jié)果就是將master分支刪除。
? ? ? ? 既然追蹤分支這么好用,那么我們怎么建立追蹤分支呢,有兩種方式,第一種方式是根絕遠(yuǎn)程分支創(chuàng)建追蹤分支,如果不指定該追蹤分支的名字,默認(rèn)和遠(yuǎn)程倉庫的分支名字一樣:git checkout –track origin/test,這樣我們就建立了一個名為test的追蹤分支,如果重新指定追蹤分支的名字:git checkout -b name origin/test,這樣我們就創(chuàng)建了一個名為name的追蹤分支,它對應(yīng)遠(yuǎn)程倉庫的test分支。第二種方式是已經(jīng)存在某個本地分支,要讓它來對應(yīng)某個遠(yuǎn)程分支來成為追蹤分支,也有兩個命令可以用,git branch –set-upstream test origin/test 或者git branch -f –track test origin/test 這里我們就讓我們本地已經(jīng)存在的test分支來追蹤遠(yuǎn)程的test分支。
git分支管理
? ? ? ? git創(chuàng)建分支于合并分支是如此簡單快捷,那么在我們的開發(fā)過程中可以瘋狂的使用分支,而且git的核心玩法之一就是分支,非常提倡使用分支,但是是不是我們可以肆無忌憚的使用分支呢,創(chuàng)建這么多的分支我們要如何來管理呢,分支不在多而在恰到好處,如果分支創(chuàng)建多了,管理起來就麻煩了,所以推薦一種分支的管理策略,git-flow,同時推薦一篇文章來了解這種策略:http://nvie.com/posts/a-successful-git-branching-model/,讓你的git使用更加順手。
推薦學(xué)習(xí):《Git教程》