簡(jiǎn)介
使用分支意味著你可以把你的工作從開(kāi)發(fā)主線上分離出來(lái)了袁,以免影響開(kāi)發(fā)主線朗恳。雖然幾乎所有的版本控制系統(tǒng)都支持分支,但是Git的尤其出眾载绿,可以說(shuō)是其脫穎而出的一個(gè)重要技能粥诫。在Git中處理分支非常的輕量,創(chuàng)建新分支這一操作幾乎瞬間完成崭庸,并且在不同分支上的切換也同樣便捷怀浆,所以git鼓勵(lì)的在正常工作流程中頻繁使用分支與合并。
基礎(chǔ)
在git中版本庫(kù)保存的不是文件的變化或差異怕享,而是一系列不同時(shí)刻的文件快照执赡。在進(jìn)行提交操作時(shí),git會(huì)保存一個(gè)提交對(duì)象函筋。該提交對(duì)象中包含一個(gè)指向暫存內(nèi)容快照的指針沙合,還包括作者的姓名、郵箱跌帐、提交時(shí)輸入的信息以及指向它的父對(duì)象的指針首懈。
假設(shè)現(xiàn)在有一個(gè)工作目錄,里面包含三個(gè)將要被暫存和提交的文件含末,暫存操作會(huì)為每一個(gè)文件計(jì)算校驗(yàn)和猜拾,然后會(huì)把單簽版本的文件快照保存到Git倉(cāng)庫(kù)中(git使用blob對(duì)象保存他們),最終將校驗(yàn)和加入到暫存區(qū)等待提交:
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'
當(dāng)使用git commit進(jìn)行提交操作時(shí)佣盒,Git會(huì)先計(jì)算每一個(gè)子目錄的校驗(yàn)和挎袜,然后在git倉(cāng)庫(kù)中將這些校驗(yàn)和保存為樹(shù)對(duì)象,隨后肥惭,git便會(huì)創(chuàng)建一個(gè)提交對(duì)象盯仪,它除了包含上面提交的那些信息外,還包含指向這個(gè)樹(shù)對(duì)象的指針蜜葱,如此一來(lái)全景,Git就可以在需要的時(shí)候重現(xiàn)此次保存的快照。
現(xiàn)在git倉(cāng)庫(kù)中有五個(gè)對(duì)象:三個(gè)blob對(duì)象(保存文件快照)牵囤、一個(gè)樹(shù)對(duì)象(記錄目錄結(jié)構(gòu)和blob對(duì)象索引)以及一個(gè)提交對(duì)象(包含著指向樹(shù)對(duì)象的指針以及所有提交信息)
此時(shí)我們對(duì)做些修改再次提交爸黄,那么這次產(chǎn)生的提交對(duì)象會(huì)包含一個(gè)指向上一次提交對(duì)象的指針。
git的分支揭鳞,其實(shí)質(zhì)上僅僅是指向提交對(duì)象的可變指針炕贵。git的默認(rèn)分支名字是master。多次提交操作后野崇,你其實(shí)已經(jīng)有一個(gè)指向最后那個(gè)提交對(duì)象的master分支称开。它會(huì)在每次提交操作中自動(dòng)向前移動(dòng)。在git中master分支并不是一個(gè)特殊的分支,它跟其他分支沒(méi)有任何區(qū)別鳖轰,之所以幾乎每個(gè)倉(cāng)庫(kù)都有master分支清酥,是因?yàn)間it init命令默認(rèn)創(chuàng)建他們了它,且大家都懶得改它蕴侣。就跟clone倉(cāng)庫(kù)一樣焰轻,默認(rèn)創(chuàng)建的就是origin。
而git的分支創(chuàng)建也尤其簡(jiǎn)單昆雀,只是為你創(chuàng)建了一個(gè)可移動(dòng)的新指針鹦马,比如創(chuàng)建一個(gè)testing分支git branch testing,就會(huì)在當(dāng)前所在的提交對(duì)象上創(chuàng)建一個(gè)指針。
而Git內(nèi)部維護(hù)了一個(gè)特殊的名為HEAD的指針忆肾,這個(gè)指針指向當(dāng)前所在的本地分支(看可以將HEAD想象為當(dāng)前分支的別名)。在你創(chuàng)建一個(gè)新分支時(shí)并不會(huì)自動(dòng)切換到新的分支上菱肖,所有此時(shí)HEAD還是指向master分支:
而我們切換分支也非常簡(jiǎn)單客冈,就是將HEAD指針指向要切換的分支指針就好了,git checkout testing:
此時(shí)你的改動(dòng)都是在testing分支上進(jìn)行稳强,而master還停留在其中的某一次提交上场仲,也就是說(shuō)你的testing分支向前移動(dòng)了,但是master沒(méi)有:
這個(gè)時(shí)候你還可以通過(guò) git checkout master將分支切換回master分支:
這條命令會(huì)做兩件事退疫,一個(gè)是使HEAD指回master分支渠缕,二是將工作目錄恢復(fù)成master分支所指向的快照內(nèi)容。也就是說(shuō)項(xiàng)目將始于一個(gè)較舊的版本褒繁。如果git不能干凈利落的完成這個(gè)任務(wù)亦鳞,它將禁止切換分支。
此后你還可以繼續(xù)在master分支上工作棒坏,這時(shí)項(xiàng)目上就出現(xiàn)了分叉燕差,因?yàn)閯偛艅?chuàng)建了一個(gè)新分支,并切換過(guò)去進(jìn)行一些工作坝冕,隨后又切換回master分支進(jìn)行了另一些工作徒探,上述兩次改動(dòng)針對(duì)的是不同分支:你可以在不同分支間不斷的來(lái)回切換和工作,并在時(shí)機(jī)成熟時(shí)將他們合并起來(lái)喂窟。
由于git分支實(shí)質(zhì)上僅包含所指對(duì)象校驗(yàn)和的文件测暗,所以它的創(chuàng)建和銷毀都異常高效。不同于大多數(shù)版本控制系統(tǒng)的分支創(chuàng)建都是將所有項(xiàng)目文件復(fù)制一遍來(lái)完成磨澡,而Git中任何規(guī)模的項(xiàng)目后能瞬間創(chuàng)建新分支碗啄。
分支的新建與合并
讓我們來(lái)假設(shè)一個(gè)類似的工作流:
- 開(kāi)發(fā)某個(gè)網(wǎng)站
- 為實(shí)現(xiàn)某個(gè)新需求,創(chuàng)建一個(gè)分支
- 在這個(gè)分支上開(kāi)展工作
這個(gè)時(shí)候钱贯,突發(fā)BUG需要緊急處理: - 切換到你的線上分支(production branch)
- 為這個(gè)緊急任務(wù)以線上分支為基礎(chǔ)新建一個(gè)分支挫掏,并在其中修復(fù)他們
- 測(cè)試通過(guò)后,切換回線上分支秩命,然后合并這個(gè)修補(bǔ)分支尉共,最后將改動(dòng)推送到線上分支
- 切換回你最初的開(kāi)發(fā)分支上繼續(xù)工作褒傅。
我們正對(duì)于上面的工作流來(lái)講解:
- 首先我們有一個(gè)線上分支用于部署,通常就是master分支
- 新建開(kāi)發(fā)分支并切換到開(kāi)發(fā)分支上進(jìn)行新需求開(kāi)發(fā):
git branch iss53
git checkout iss53
你也可以在git branch中使用-b參數(shù)來(lái)新建后自動(dòng)切換:
git branch -b iss53
3.此時(shí)我們就在開(kāi)發(fā)分支上工作袄友,你可能已經(jīng)有多次提交殿托,該分支是要領(lǐng)先于master分支的
- 此時(shí)遇到緊急情況,說(shuō)線上分支即master分支上出現(xiàn)BUG需要緊急修復(fù)
- 此時(shí)切換到master分支剧蚣,并且創(chuàng)建修復(fù)分支:
git checkout master
git branch -b hotfix
-
在hotfix基礎(chǔ)上進(jìn)行開(kāi)發(fā)支竹,這個(gè)時(shí)候分支是出現(xiàn)分叉了的。
測(cè)試問(wèn)題解決后鸠按,將其合并到你的master分支來(lái)部署到線上
git checkout master
git merge hotfix
git merge是合并分支的意思礼搁,在這里這個(gè)合并是fast-forward的,由于當(dāng)前master分支所指向的提交是你當(dāng)前提交(hotfix的提交)的直接上游目尖,所有g(shù)it只是簡(jiǎn)單的將指針向前移動(dòng)馒吴,換句話說(shuō),當(dāng)你試圖合并兩個(gè)分支時(shí)瑟曲,如果順著一個(gè)分支走下去能夠達(dá)到另一個(gè)分支饮戳,那么git在合并兩者的時(shí)候只會(huì)簡(jiǎn)單的將指針向前推進(jìn),這種情況下的合并操作并不需要解決分歧的問(wèn)題就叫做fast-forward.
- 完成了線上分支的緊急修復(fù)并且將修復(fù)與線上分支合并后洞拨,我們可以刪除這個(gè)hotfix分支扯罐,因?yàn)槟阋呀?jīng)不需要他們了,master這個(gè)線上分支已經(jīng)指向了同樣的位置,而要?jiǎng)h除分支需要-d選項(xiàng)
git branch -d hotfix
- 然后我們切換到開(kāi)發(fā)分支iss53來(lái)繼續(xù)工作烦衣。
git checkout iss53
經(jīng)過(guò)我們?cè)趇ss53上工作并不斷提交歹河,你在hotfix分支上所做的工作并沒(méi)有包含到iss53分支中,如果你需要拉取hotfix所做的修改琉挖,就需要使用git merge master命令將master分支合并到iss53分支启泣,或者也可以等iss53完成其任務(wù)后,合并到master分支上示辈。
- 最后我們終于完成了iss53任務(wù)寥茫,并打算將其合并入master分支中,你只需要切換到要合并的分支執(zhí)行merge命令即可:
git checkout master
git merge iss53
這和之前hotfix有一個(gè)地方不一樣矾麻,因?yàn)槟愕拈_(kāi)發(fā)分支從 一個(gè)更早的地方開(kāi)始分叉纱耻,因?yàn)閙aster分支所指向的提交并不是iss53分支所指向的提交的直接祖先,git不得不做一些額外的工作险耀,出現(xiàn)這種情況的時(shí)候弄喘,git會(huì)使用兩個(gè)分支的末端所指的快照(途中的C4 C5)以及這兩個(gè)分支的共同祖先(C2),做一個(gè)簡(jiǎn)單的三方合并,和之前分支指針向前推進(jìn)所不同的是甩牺,git將此次三方合并的結(jié)果做了一個(gè)新的快照并且自動(dòng)創(chuàng)建一個(gè)新的提交指向他蘑志,這個(gè)被稱作一次合并提交,他的特別之處在于他不止一個(gè)父提交。
- 合并提交并不是一定都非常順利急但,如果你在兩個(gè)不同的分支中澎媒,對(duì)同一個(gè)文件進(jìn)行了不同的修改,也就是要合并的分支(C4 C5)以及他們合并的基礎(chǔ)分支(C2)中同一個(gè)文件的校驗(yàn)和不同波桩,這個(gè)時(shí)候git就沒(méi)法干凈的合并它們戒努,此時(shí)就會(huì)產(chǎn)生合并沖突:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
此時(shí)git做了合并,但是并沒(méi)有自動(dòng)創(chuàng)建一個(gè)新的合并提交镐躲,git會(huì)暫停下來(lái)储玫,等待你去解決合并產(chǎn)生的沖突。你此時(shí)可以使用git status來(lái)查看哪些因包含合并沖突而處于未合并狀態(tài)(unmerged)的文件:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
任何因包含合并沖突而有待解決的文件萤皂,都會(huì)以未合并狀態(tài)標(biāo)識(shí)出來(lái)(Unmerged paths)撒穷。git會(huì)在有沖突的文件中加入標(biāo)準(zhǔn)的沖突解決標(biāo)記,這樣你可以打開(kāi)這些包含沖突的文件然后手動(dòng)解決沖突裆熙,出現(xiàn)沖突的文件會(huì)包含一些特殊區(qū)段桥滨,看起來(lái)像下面的樣子:
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
這表示HEAD所指向的版本(也就是你的master分支所在的位置,因?yàn)槟阍谶\(yùn)行merge命令的時(shí)候已經(jīng)檢出到了這個(gè)分支)在這個(gè)區(qū)段的上半部分弛车,而iss53分支所指示的版本是下半部分,他們之間使用"======="分隔開(kāi)蒲每。為了解決沖突纷跛,你必須選擇使用由“=======”分割的兩個(gè)部分中的一個(gè),或則你也可以自行合并這些內(nèi)容邀杏。例如你將上一段內(nèi)容換成下面的樣子:
<div id="footer">
please contact us at email.support@github.com
</div>
上述的沖突解決方案僅僅保留了其中一個(gè)分支的修改贫奠,并且一些二外的符號(hào)也被完全刪除,在你解決了所有文件里面的所有沖突后望蜡,對(duì)每個(gè)文件使用git add命令來(lái)將其暫存唤崭,git就會(huì)將他們標(biāo)記為沖突已解決。
你也可以使用圖形化的工具來(lái)解決沖突脖律,運(yùn)行 git mergetool谢肾,該命令會(huì)啟動(dòng)一個(gè)合適的可視化合并工具,并帶領(lǐng)你一步步解決這些沖突小泉。等你退出合并工具之后芦疏,git會(huì)詢問(wèn)你剛才的合并是否完成。此時(shí)就可以放心的git add和git commit 了微姊。
分支管理
列出當(dāng)前所有分支
git branch
其中你現(xiàn)在的工作分支(即HEAD指針指向的分支)前會(huì)有個(gè)星號(hào)酸茴。這意味著你在這個(gè)時(shí)候的所有提交都是都會(huì)在該分支上移動(dòng)。
查看每一個(gè)分支的最后一次提交
git branch -v
查看分支合并
- 查看哪一個(gè)分支合并到當(dāng)前分支
git branch --merged
- 查看哪一個(gè)分支尚未合并到當(dāng)前分支
git branch --no-merged
強(qiáng)制刪除未合并分支
如果一個(gè)分支沒(méi)有被合并到其他分支兢交,你直接使用-d刪除會(huì)導(dǎo)致失敗薪捍,如果確定要?jiǎng)h除它可以使用-D來(lái)強(qiáng)制刪除未合并的分支。
遠(yuǎn)程分支
假設(shè)網(wǎng)絡(luò)上有一個(gè)在git.ourcompany.com的git服務(wù)器,如果你從這里clone酪穿,git會(huì)為你自動(dòng)將其命名為origin凳干,拉取它的所有數(shù)據(jù)并創(chuàng)建一個(gè)指向它的master分支的指針,并且在本地將其命名為origin/master昆稿,git也會(huì)給你一個(gè)與origin的master分支在指向同一個(gè)地方的本地master分支纺座,這就是你工作的基礎(chǔ)「忍叮可以理解為你本地的git版本庫(kù)目前維護(hù)了兩個(gè)分支净响,一個(gè)遠(yuǎn)程分支origin/master一個(gè)是本地分支master。
在這個(gè)基礎(chǔ)上你在本地的master分支上工作喳瓣,與此同時(shí)馋贤,其他人也可能會(huì)往遠(yuǎn)程服務(wù)器上提交并更新了master分支,此時(shí)你的提交歷史將向不同的方向前進(jìn)畏陕。但是只要你不與origin服務(wù)器連接配乓,你的origin/master指針就不會(huì)移動(dòng):
如果要同步你的工作,運(yùn)行g(shù)it fetch origin命令惠毁,從中抓取本地沒(méi)有的數(shù)據(jù)犹芹,并且更新本地?cái)?shù)據(jù)庫(kù),移動(dòng)origin/master指針指向新的鞠绰、更新后的位置腰埂。
使用git fetch命令從服務(wù)器上抓取本地沒(méi)有的數(shù)據(jù)時(shí),它并不會(huì)修改工作目錄中的內(nèi)容蜈膨,它只會(huì)獲取數(shù)據(jù)然后讓你自己合并屿笼。git還提供了git pull命令來(lái)自動(dòng)合并其大多數(shù)情況下的含義就是一個(gè)git fetch緊接著一個(gè)git merge命令。不過(guò)最好還是fetch與merge來(lái)合并翁巍,畢竟單獨(dú)使用更加知道自己干了什么驴一。
推送
目前我們讓有一個(gè)遠(yuǎn)程跟蹤分支origin/master,這個(gè)時(shí)候有一個(gè)需求灶壶,我們想要將目前的開(kāi)發(fā)分支分享出去肝断,這就需要我們創(chuàng)建一個(gè)新的遠(yuǎn)程跟蹤分支。例如你希望和別人一起在名為serverfix的分支上工作:
$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
* [new branch] serverfix -> serverfix
這樣遠(yuǎn)程就有了一個(gè)origin/serverfix跟蹤分支驰凛,git push origin serverfix是一個(gè)簡(jiǎn)寫(xiě)形式孝情,當(dāng)你想讓遠(yuǎn)程分支與本地分支同名是可以這樣寫(xiě)。如果不同名時(shí)可以寫(xiě)成:git push origin serverfix:awesomebranch 這樣就是將本地serverfix分支推送到遠(yuǎn)程倉(cāng)庫(kù)上的awesomebranch分支洒嗤。
下一次其他協(xié)作者從服務(wù)器上抓取數(shù)據(jù)時(shí)箫荡,他們會(huì)在本地生成一個(gè)遠(yuǎn)程分支origin/serverfix,指向服務(wù)器的serverfix分支的引用。
$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
* [new branch] serverfix -> origin/serverfix
需要特別注意的是渔隶,當(dāng)抓取到新的遠(yuǎn)程跟蹤分支時(shí)羔挡,本地不會(huì)自動(dòng)生成一份可編輯的副本洁奈,換句話說(shuō)就是不會(huì)生成一個(gè)新的本地的serverfix分支,只是一個(gè)不可以修改的origin/serverfix指針绞灼,這個(gè)時(shí)候你有兩種途徑來(lái)使用它:
- 將這個(gè)遠(yuǎn)程分支合并到當(dāng)前所在的分支上
git merge origin/serverfix
- 你也可以創(chuàng)建一個(gè)自己的serverfix分支來(lái)工作:
git checkout -b serverfix origin/serverfix
跟蹤分支
從一個(gè)遠(yuǎn)程跟蹤分支檢出一個(gè)本地分支會(huì)自動(dòng)創(chuàng)建所謂的跟蹤分支(它跟蹤的分支叫做上游分支)利术。跟蹤分支是于遠(yuǎn)程分支有直接關(guān)系的本地分支。如果在一個(gè)跟蹤分支上輸入git pull低矮,git能自動(dòng)識(shí)別去哪個(gè)服務(wù)器上抓取印叁、合并到哪個(gè)分支。
當(dāng)克隆一個(gè)倉(cāng)庫(kù)時(shí)军掂,它通常會(huì)自動(dòng)地創(chuàng)建一個(gè)跟蹤origin/master的master分支(這個(gè)master分支就是一個(gè)跟蹤分支,其跟蹤的是遠(yuǎn)程分支origin/master)轮蜕。當(dāng)然你也可以設(shè)置其他的跟蹤分支,或則一個(gè)其他遠(yuǎn)程服務(wù)器上的跟蹤分支:
git checkout -b [branch] [remote_name/branch]
你也可以設(shè)置已有的本地分支來(lái)跟蹤一個(gè)剛剛拉取下來(lái)的遠(yuǎn)程分支蝗锥,或則想要修改正在跟蹤的上游分支跃洛,可以使用-u選項(xiàng)運(yùn)行g(shù)it branch來(lái)設(shè)置:
git branch -u origin/serverfix
如果想要查看設(shè)置的所有跟蹤分支,可以使用git branch -vv來(lái)查看终议,這將所有的本地分支列出來(lái)并且包含更多信息:
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
上面可以看到iss53分支正在跟蹤origin/iss53并且ahead是2汇竭,意味著本地有兩個(gè)提交還沒(méi)有推送到服務(wù)器上,而master分支正在跟蹤origin/master分支并且是最新的穴张。serverfix分支跟蹤teamone服務(wù)器上的server-fix-good分支并且領(lǐng)先3落后1细燎,意味著服務(wù)器上又一次提交還沒(méi)有合并并且同時(shí)本地上有三次提交還沒(méi)有推送。最后看到testing分支并沒(méi)有跟蹤任何遠(yuǎn)程分支皂甘,表示本地使用的分支找颓。
這里需要注意的是這些數(shù)字的值來(lái)自于你從每個(gè)服務(wù)器最后一次抓取的數(shù)據(jù),這個(gè)命令并不會(huì)連接服務(wù)器叮贩,它只是告訴你關(guān)于本地緩存的數(shù)據(jù),如果想要統(tǒng)計(jì)最新的領(lǐng)先于落后數(shù)據(jù)佛析,需要在運(yùn)行此命令時(shí)先抓取所有遠(yuǎn)程倉(cāng)庫(kù):
git fetch --all
git branch -vv
刪除遠(yuǎn)程分支
假設(shè)你已經(jīng)通過(guò)遠(yuǎn)程分支做完所有的工作益老,也就是說(shuō)你和你的協(xié)作者已經(jīng)完成了一個(gè)任務(wù)并將其合并到遠(yuǎn)程倉(cāng)庫(kù)的master分支上,可以使用--delete選項(xiàng)的git push命令來(lái)刪除一個(gè)遠(yuǎn)程分支:
git push origin --delete serverfix
基本上這個(gè)命令做的只是從服務(wù)器上移除這個(gè)指針寸莫,git服務(wù)器通常會(huì)保留數(shù)據(jù)一段時(shí)間知道垃圾回收運(yùn)行捺萌,所有如果不小心刪除掉了,還是可以恢復(fù)的膘茎。
變基
在git中整合來(lái)自不同分支的修改有兩種方法:前面我們介紹過(guò)merge即合并分支桃纯,git還提供了rebase變基來(lái)整合。
當(dāng)你看到開(kāi)發(fā)任務(wù)分叉到兩個(gè)不同的分支后披坏,又各自提交了更新:
使用merge命令态坦,他會(huì)將兩個(gè)分支的最新快照C3和C4以及二者最近的共同祖先(C2)進(jìn)行三方合并,合并的結(jié)果是生成一個(gè)新的快照并提交棒拂,這個(gè)新的快照擁有兩個(gè)父提交:
而還有一種方法就是提取在C4中引入的補(bǔ)丁和修改伞梯,然后在C3的基礎(chǔ)上應(yīng)用一次玫氢,而這就叫做變基。你可以使用rebase命令將提交到某一分支上的所有修改都移至另一個(gè)分支上谜诫。
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
其原理是首先找到這兩個(gè)分支即當(dāng)前分支experiment漾峡、變基操作的目標(biāo)基底分支master的最近共同祖先C2,然后對(duì)比當(dāng)前分支相對(duì)于該祖先的歷次提交喻旷,提取相應(yīng)的修改并存為臨時(shí)文件生逸,然后將當(dāng)前分支指向目標(biāo)基底C3,最后以此將之前另存為臨時(shí)文件的修改以此應(yīng)用且预。
現(xiàn)在我們回到master分支上槽袄,進(jìn)行一次快速合并:
git checkout master
git merge experiment
此時(shí)C4指向的快照和上面使用merge命令中C5指向的快照一模一樣了,這兩種整合方法的最終結(jié)果沒(méi)有任何區(qū)別辣之,當(dāng)時(shí)變基使提交歷史更加整潔掰伸。你在查看一個(gè)經(jīng)過(guò)變基的分支的歷史記錄時(shí)會(huì)發(fā)現(xiàn),盡管實(shí)際的開(kāi)發(fā)工作是并行的怀估,但他們看上去就像是串行的一樣狮鸭,提交歷史是一條直線沒(méi)有分叉。
總結(jié)
分支是git的一個(gè)殺手锏級(jí)武器多搀,也可以說(shuō)是其能夠如此流行的一個(gè)重要原因歧蕉,但是其概念較多、而且還有遠(yuǎn)程分支概念康铭,理解起來(lái)會(huì)相對(duì)麻煩些惯退,但是其使用頻繁可以說(shuō)你平常的操作除了add 和 commit 外,分支的管理是最常見(jiàn)的从藤,必須加深理解并能夠靈活運(yùn)用催跪。
分支的作用
分支就是可以把你的工作從開(kāi)發(fā)主線上分離出來(lái),以免影響開(kāi)發(fā)主線夷野。通常我們有一個(gè)master分支這個(gè)分支上完全穩(wěn)定的代碼就相當(dāng)于軟件的穩(wěn)定版懊蒸,還有一個(gè)develop分支這個(gè)分支上可能有一些新的特性還不是太穩(wěn)定你可以嘗試下載,就相當(dāng)于軟件的dev版本悯搔,還可以有bata等骑丸,你實(shí)際開(kāi)發(fā)的時(shí)候選擇從一個(gè)分支上創(chuàng)建另一個(gè)分支來(lái)開(kāi)發(fā),如果開(kāi)發(fā)完成了將其先合并到develop分支上用于測(cè)試妒貌,帶develop分支上都穩(wěn)定了通危,可以合并到master發(fā)布穩(wěn)定版」嗍铮基本長(zhǎng)期開(kāi)發(fā)軟件都是這個(gè)流程菊碟。本地分支的一些操作
git branch # 列出當(dāng)前git倉(cāng)庫(kù)的所有分支
git branch -v # 列出當(dāng)前git倉(cāng)庫(kù)所有分支最新的一次提交
git branch --merged # 列出已經(jīng)合并到當(dāng)前分支的分支
git branch --no-merged # 列出尚未合并到當(dāng)前分支的分支
git branch branch_name # 創(chuàng)建新分支
git checkout branch_name # 切換到一個(gè)分支
git branch -b branch_name # 創(chuàng)建一個(gè)新分支并切換到這個(gè)新分支
git merge branch_name # 將一個(gè)分支合并到當(dāng)前分支上
git branch -d branch_name # 刪除一個(gè)分支
git branch -D branch_name # 強(qiáng)制刪除一個(gè)分支
- 什么是遠(yuǎn)程分支,為什么要有遠(yuǎn)程分支
分支的作用是將工作從開(kāi)發(fā)主線中分離出來(lái)在刺,而git的另一個(gè)用途就是協(xié)作框沟,而遠(yuǎn)程分支的作用就是講分支提供到服務(wù)器上以便大家共同開(kāi)發(fā)藏古。
我們使用git clone克隆遠(yuǎn)程倉(cāng)庫(kù)后默認(rèn)給我們生成了一個(gè)origin/master這個(gè)遠(yuǎn)程分支,而本地有一個(gè)master分支來(lái)跟蹤origin/master這個(gè)遠(yuǎn)程分支忍燥。這里面的兩個(gè)概念為:origin是遠(yuǎn)程服務(wù)器地址的別名拧晕,origin/master遠(yuǎn)程分支的名字, 而master是一個(gè)遠(yuǎn)程跟蹤分支梅垄,跟蹤的是origin/master厂捞。
如果是個(gè)人開(kāi)發(fā)者,在本地開(kāi)發(fā)完成后合并到本地的master分支上队丝,然后推送到遠(yuǎn)程的origin/master分支上就可以了靡馁,不需要在遠(yuǎn)程建立其他分支。
而對(duì)于需要協(xié)作的開(kāi)發(fā)團(tuán)隊(duì)机久,我們需要保證master這穩(wěn)定分支不變臭墨,而提供一個(gè)origin/dev這樣的遠(yuǎn)程分支來(lái)進(jìn)行開(kāi)發(fā),此時(shí)你就可以在本地創(chuàng)建一個(gè)dev分支來(lái)跟蹤這個(gè)遠(yuǎn)程分支膘盖。這就是遠(yuǎn)程分支的作用:協(xié)作
- 遠(yuǎn)程分支的一些操作
git clone url # 克隆倉(cāng)庫(kù)胧弛,創(chuàng)建一個(gè)本地master分支指向origin/master這個(gè)遠(yuǎn)程分支
git fetch origin # 同步遠(yuǎn)程分支到本地,這并不改變工作目錄的內(nèi)容
git pull origin # 同步遠(yuǎn)程分支并與本地分支合并相當(dāng)于 git fetch后緊跟一個(gè)git merge
git push remote_name branch_name:remote_branch_name # 在遠(yuǎn)程分支上創(chuàng)建一個(gè)remote_branch_name分支并且將本地的branch_name分支內(nèi)容推送上去
git merge remote/remote_branch_name #將遠(yuǎn)程分支合并到當(dāng)前分支
git checkout -b branch_name remote/remote_branch_name # 新建一個(gè)遠(yuǎn)程跟蹤分支branch_name來(lái)跟蹤遠(yuǎn)程分支
git branch -u reomte/reomte_branch_name # 設(shè)置當(dāng)前分支跟蹤遠(yuǎn)程分支
git branch -vv #列出所有遠(yuǎn)程跟蹤分支以及一些詳細(xì)信息
git push remote --delete branch_name # 從服務(wù)器上刪除一個(gè)分支
- 變基與合并
變基與合并雖然得到的結(jié)果是一樣的侠畔,但是變基破壞了倉(cāng)庫(kù)的提交歷史结缚,但是其又保證了提交的整潔所以具體使用哪一個(gè)都有道理。而總的原則是软棺,只對(duì)尚未推送或分享給別人的本地修改執(zhí)行變基操作清理歷史红竭,從不對(duì)已推送到別處的提交執(zhí)行變基操作,這樣你才能享受兩種方式帶來(lái)的便利喘落。