Git 深入 - 分支的新建與合并

分支的新建與合并

讓我們來(lái)看一個(gè)簡(jiǎn)單的分支新建與分支合并的例子兼砖,實(shí)際工作中你可能會(huì)用到類(lèi)似的工作流强法。 你將經(jīng)歷如下步驟:

  1. 開(kāi)發(fā)某個(gè)網(wǎng)站份帐。

  2. 為實(shí)現(xiàn)某個(gè)新的需求蟹肘,創(chuàng)建一個(gè)分支词疼。

  3. 在這個(gè)分支上開(kāi)展工作。

正在此時(shí)帘腹,你突然接到一個(gè)電話(huà)說(shuō)有個(gè)很?chē)?yán)重的問(wèn)題需要緊急修補(bǔ)贰盗。 你將按照如下方式來(lái)處理:

  1. 切換到你的線(xiàn)上分支(production branch)。

  2. 為這個(gè)緊急任務(wù)新建一個(gè)分支阳欲,并在其中修復(fù)它舵盈。

  3. 在測(cè)試通過(guò)之后,切換回線(xiàn)上分支球化,然后合并這個(gè)修補(bǔ)分支秽晚,最后將改動(dòng)推送到線(xiàn)上分支。

  4. 切換回你最初工作的分支上筒愚,繼續(xù)工作赴蝇。

新建分支

首先,我們假設(shè)你正在你的項(xiàng)目上工作巢掺,并且已經(jīng)有一些提交句伶。

一個(gè)簡(jiǎn)單的提交歷史。

Figure 18. 一個(gè)簡(jiǎn)單提交歷史

現(xiàn)在陆淀,你已經(jīng)決定要解決你的公司使用的問(wèn)題追蹤系統(tǒng)中的 #53 問(wèn)題考余。 想要新建一個(gè)分支并同時(shí)切換到那個(gè)分支上,你可以運(yùn)行一個(gè)帶有 -b 參數(shù)的 git checkout 命令:

$ git checkout -b iss53
Switched to a new branch "iss53"

它是下面兩條命令的簡(jiǎn)寫(xiě):

$ git branch iss53
$ git checkout iss53
創(chuàng)建一個(gè)新分支指針轧苫。

Figure 19. 創(chuàng)建一個(gè)新分支指針

你繼續(xù)在 #53 問(wèn)題上工作楚堤,并且做了一些提交。 在此過(guò)程中含懊,iss53 分支在不斷的向前推進(jìn)钾军,因?yàn)槟阋呀?jīng)檢出到該分支(也就是說(shuō),你的 HEAD 指針指向了 iss53 分支)

$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
iss53 分支隨著工作的進(jìn)展向前推進(jìn)绢要。

Figure 20. iss53 分支隨著工作的進(jìn)展向前推進(jìn)

現(xiàn)在你接到那個(gè)電話(huà)吏恭,有個(gè)緊急問(wèn)題等待你來(lái)解決。 有了 Git 的幫助重罪,你不必把這個(gè)緊急問(wèn)題和 iss53 的修改混在一起樱哼,你也不需要花大力氣來(lái)還原關(guān)于 53# 問(wèn)題的修改哀九,然后再添加關(guān)于這個(gè)緊急問(wèn)題的修改,最后將這個(gè)修改提交到線(xiàn)上分支搅幅。 你所要做的僅僅是切換回 master 分支阅束。

但是,在你這么做之前茄唐,要留意你的工作目錄和暫存區(qū)里那些還沒(méi)有被提交的修改息裸,它可能會(huì)和你即將檢出的分支產(chǎn)生沖突從而阻止 Git 切換到該分支。 最好的方法是沪编,在你切換分支之前呼盆,保持好一個(gè)干凈的狀態(tài)。 有一些方法可以繞過(guò)這個(gè)問(wèn)題(即蚁廓,保存進(jìn)度(stashing) 和 修補(bǔ)提交(commit amending))访圃,我們會(huì)在 儲(chǔ)藏與清理 中看到關(guān)于這兩個(gè)命令的介紹。 現(xiàn)在相嵌,我們假設(shè)你已經(jīng)把你的修改全部提交了腿时,這時(shí)你可以切換回 master 分支了:

$ git checkout master
Switched to branch 'master'

這個(gè)時(shí)候,你的工作目錄和你在開(kāi)始 #53 問(wèn)題之前一模一樣饭宾,現(xiàn)在你可以專(zhuān)心修復(fù)緊急問(wèn)題了批糟。 請(qǐng)牢記:當(dāng)你切換分支的時(shí)候,Git 會(huì)重置你的工作目錄看铆,使其看起來(lái)像回到了你在那個(gè)分支上最后一次提交的樣子跃赚。 Git 會(huì)自動(dòng)添加、刪除性湿、修改文件以確保此時(shí)你的工作目錄和這個(gè)分支最后一次提交時(shí)的樣子一模一樣。

接下來(lái)满败,你要修復(fù)這個(gè)緊急問(wèn)題肤频。 讓我們建立一個(gè)針對(duì)該緊急問(wèn)題的分支(hotfix branch),在該分支上工作直到問(wèn)題解決:

$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix 1fb7853] fixed the broken email address
 1 file changed, 2 insertions(+)
基于 `master` 分支的緊急問(wèn)題分支(hotfix branch)算墨。

Figure 21. 基于 master 分支的緊急問(wèn)題分支 hotfix branch

你可以運(yùn)行你的測(cè)試宵荒,確保你的修改是正確的,然后將其合并回你的 master 分支來(lái)部署到線(xiàn)上净嘀。 你可以使用 git merge 命令來(lái)達(dá)到上述目的:

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

在合并的時(shí)候报咳,你應(yīng)該注意到了"快進(jìn)(fast-forward)"這個(gè)詞。 由于當(dāng)前 master 分支所指向的提交是你當(dāng)前提交(有關(guān) hotfix 的提交)的直接上游挖藏,所以 Git 只是簡(jiǎn)單的將指針向前移動(dòng)暑刃。 換句話(huà)說(shuō),當(dāng)你試圖合并兩個(gè)分支時(shí)膜眠,如果順著一個(gè)分支走下去能夠到達(dá)另一個(gè)分支岩臣,那么 Git 在合并兩者的時(shí)候溜嗜,只會(huì)簡(jiǎn)單的將指針向前推進(jìn)(指針右移),因?yàn)檫@種情況下的合并操作沒(méi)有需要解決的分歧——這就叫做 “快進(jìn)(fast-forward)”架谎。

現(xiàn)在炸宵,最新的修改已經(jīng)在 master 分支所指向的提交快照中,你可以著手發(fā)布該修復(fù)了谷扣。

`master` 被快進(jìn)到 `hotfix`土全。

Figure 22. master 被快進(jìn)到 hotfix

關(guān)于這個(gè)緊急問(wèn)題的解決方案發(fā)布之后,你準(zhǔn)備回到被打斷之前時(shí)的工作中会涎。 然而裹匙,你應(yīng)該先刪除 hotfix分支,因?yàn)槟阋呀?jīng)不再需要它了 —— master 分支已經(jīng)指向了同一個(gè)位置在塔。 你可以使用帶 -d 選項(xiàng)的 git branch 命令來(lái)刪除分支:

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

現(xiàn)在你可以切換回你正在工作的分支繼續(xù)你的工作幻件,也就是針對(duì) #53 問(wèn)題的那個(gè)分支(iss53 分支)。

$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)
繼續(xù)在 `iss53` 分支上的工作蛔溃。

Figure 23. 繼續(xù)在 iss53 分支上的工作

你在 hotfix 分支上所做的工作并沒(méi)有包含到 iss53 分支中绰沥。 如果你需要拉取 hotfix 所做的修改,你可以使用 git merge master 命令將 master 分支合并入 iss53 分支贺待,或者你也可以等到 iss53 分支完成其使命徽曲,再將其合并回 master 分支。

分支的合并

假設(shè)你已經(jīng)修正了 #53 問(wèn)題麸塞,并且打算將你的工作合并入 master 分支秃臣。 為此,你需要合并 iss53 分支到 master 分支哪工,這和之前你合并 hotfix 分支所做的工作差不多奥此。 你只需要檢出到你想合并入的分支,然后運(yùn)行 git merge 命令:

$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

這和你之前合并 hotfix 分支的時(shí)候看起來(lái)有一點(diǎn)不一樣雁比。 在這種情況下稚虎,你的開(kāi)發(fā)歷史從一個(gè)更早的地方開(kāi)始分叉開(kāi)來(lái)(diverged)。 因?yàn)椋?code>master 分支所在提交并不是 iss53 分支所在提交的直接祖先偎捎,Git 不得不做一些額外的工作蠢终。 出現(xiàn)這種情況的時(shí)候,Git 會(huì)使用兩個(gè)分支的末端所指的快照(C4C5)以及這兩個(gè)分支的工作祖先(C2)茴她,做一個(gè)簡(jiǎn)單的三方合并寻拂。

一次典型合并中所用到的三個(gè)快照。

Figure 24. 一次典型合并中所用到的三個(gè)快照

和之前將分支指針向前推進(jìn)所不同的是丈牢,Git 將此次三方合并的結(jié)果做了一個(gè)新的快照并且自動(dòng)創(chuàng)建一個(gè)新的提交指向它祭钉。 這個(gè)被稱(chēng)作一次合并提交,它的特別之處在于他有不止一個(gè)父提交己沛。

一個(gè)合并提交朴皆。

Figure 25. 一個(gè)合并提交

需要指出的是帕识,Git 會(huì)自行決定選取哪一個(gè)提交作為最優(yōu)的共同祖先,并以此作為合并的基礎(chǔ)遂铡;這和更加古老的 CVS 系統(tǒng)或者 Subversion (1.5 版本之前)不同肮疗,在這些古老的版本管理系統(tǒng)中,用戶(hù)需要自己選擇最佳的合并基礎(chǔ)扒接。 Git 的這個(gè)優(yōu)勢(shì)使其在合并操作上比其他系統(tǒng)要簡(jiǎn)單很多伪货。

既然你的修改已經(jīng)合并進(jìn)來(lái)了,你已經(jīng)不再需要 iss53 分支了钾怔。 現(xiàn)在你可以在任務(wù)追蹤系統(tǒng)中關(guān)閉此項(xiàng)任務(wù)碱呼,并刪除這個(gè)分支。

$ git branch -d iss53

遇到?jīng)_突時(shí)的分支合并

有時(shí)候合并操作不會(huì)如此順利宗侦。 如果你在兩個(gè)不同的分支中愚臀,對(duì)同一個(gè)文件的同一個(gè)部分進(jìn)行了不同的修改先慷,Git 就沒(méi)法干凈的合并它們艾猜。 如果你對(duì) #53 問(wèn)題的修改和有關(guān) hotfix 的修改都涉及到同一個(gè)文件的同一處,在合并它們的時(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)查看那些因包含合并沖突而處于未合并(unmerged)狀態(tài)的文件:

$ 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)茴厉。 Git 會(huì)在有沖突的文件中加入標(biāo)準(zhǔn)的沖突解決標(biāo)記,這樣你可以打開(kāi)這些包含沖突的文件然后手動(dòng)解決沖突什荣。 出現(xiàn)沖突的文件會(huì)包含一些特殊區(qū)段矾缓,看起來(lái)像下面這個(gè)樣子:

<<<<<<< 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 分支所指示的版本在 ======= 的下半部分嗜闻。 為了解決沖突,你必須選擇使用由 ======= 分割的兩部分中的一個(gè)因篇,或者你也可以自行合并這些內(nèi)容。 例如笔横,你可以通過(guò)把這段內(nèi)容換成下面的樣子來(lái)解決沖突:

<div id="footer">
please contact us at email.support@github.com
</div>

上述的沖突解決方案僅保留了其中一個(gè)分支的修改竞滓,并且 <<<<<<< , ======= , 和 >>>>>>> 這些行被完全刪除了。 在你解決了所有文件里的沖突之后吹缔,對(duì)每個(gè)文件使用 git add 命令來(lái)將其標(biāo)記為沖突已解決商佑。 一旦暫存這些原本有沖突的文件,Git 就會(huì)將它們標(biāo)記為沖突已解決厢塘。

如果你想使用圖形化工具來(lái)解決沖突茶没,你可以運(yùn)行 git mergetool肌幽,該命令會(huì)為你啟動(dòng)一個(gè)合適的可視化合并工具,并帶領(lǐng)你一步一步解決這些沖突:

$ git mergetool

This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
Merging:
index.html

Normal merge conflict for 'index.html':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (opendiff):

如果你想使用除默認(rèn)工具(在這里 Git 使用 opendiff 做為默認(rèn)的合并工具抓半,因?yàn)樽髡咴?Mac 上運(yùn)行該程序)外的其他合并工具喂急,你可以在 “下列工具中(one of the following tools)” 這句后面看到所有支持的合并工具。 然后輸入你喜歡的工具名字就可以了笛求。

|

Note

|

如果你需要更加高級(jí)的工具來(lái)解決復(fù)雜的合并沖突廊移,我們會(huì)在 高級(jí)合并 介紹更多關(guān)于分支合并的內(nèi)容。

|

等你退出合并工具之后探入,Git 會(huì)詢(xún)問(wèn)剛才的合并是否成功狡孔。 如果你回答是,Git 會(huì)暫存那些文件以表明沖突已解決: 你可以再次運(yùn)行 git status 來(lái)確認(rèn)所有的合并沖突都已被解決:

$ git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

    modified:   index.html

如果你對(duì)結(jié)果感到滿(mǎn)意蜂嗽,并且確定之前有沖突的的文件都已經(jīng)暫存了苗膝,這時(shí)你可以輸入 git commit 來(lái)完成合并提交。 默認(rèn)情況下提交信息看起來(lái)像下面這個(gè)樣子:

Merge branch 'iss53'

Conflicts:
    index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#   .git/MERGE_HEAD
# and try again.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#   modified:   index.html
#

如果你覺(jué)得上述的信息不夠充分植旧,不能完全體現(xiàn)分支合并的過(guò)程辱揭,你可以修改上述信息,添加一些細(xì)節(jié)給未來(lái)檢視這個(gè)合并的讀者一些幫助隆嗅,告訴他們你是如何解決合并沖突的界阁,以及理由是什么。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胖喳,一起剝皮案震驚了整個(gè)濱河市泡躯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丽焊,老刑警劉巖较剃,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異技健,居然都是意外死亡写穴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)雌贱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)啊送,“玉大人,你說(shuō)我怎么就攤上這事欣孤〔雒唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵降传,是天一觀的道長(zhǎng)篷朵。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么声旺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任笔链,我火速辦了婚禮,結(jié)果婚禮上腮猖,老公的妹妹穿的比我還像新娘鉴扫。我一直安慰自己,他們只是感情好缚够,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布幔妨。 她就那樣靜靜地躺著,像睡著了一般谍椅。 火紅的嫁衣襯著肌膚如雪误堡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,985評(píng)論 1 291
  • 那天雏吭,我揣著相機(jī)與錄音锁施,去河邊找鬼。 笑死杖们,一個(gè)胖子當(dāng)著我的面吹牛悉抵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摘完,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼姥饰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了孝治?” 一聲冷哼從身側(cè)響起列粪,我...
    開(kāi)封第一講書(shū)人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谈飒,沒(méi)想到半個(gè)月后岂座,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杭措,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年费什,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片手素。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸳址,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泉懦,到底是詐尸還是另有隱情稿黍,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布祠斧,位于F島的核電站闻察,受9級(jí)特大地震影響拱礁,放射性物質(zhì)發(fā)生泄漏琢锋。R本人自食惡果不足惜辕漂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吴超。 院中可真熱鬧钉嘹,春花似錦、人聲如沸鲸阻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鸟悴。三九已至陈辱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間细诸,已是汗流浹背沛贪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留震贵,地道東北人利赋。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像猩系,于是被迫代替她去往敵國(guó)和親媚送。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 3.2 Git 分支 - 分支的新建與合并 分支的新建與合并 讓我們來(lái)看一個(gè)簡(jiǎn)單的分支新建與分支合并的例子寇甸,實(shí)際工...
    旅行者xy閱讀 1,032評(píng)論 0 6
  • 分支的新建與合并 讓我們來(lái)看一個(gè)簡(jiǎn)單的分支新建與分支合并的例子塘偎,實(shí)際工作中你可能會(huì)用到類(lèi)似的工作流。 你將經(jīng)歷如下...
    vb12閱讀 728評(píng)論 0 0
  • 3.2 Git 分支 - 分支的新建與合并 分支的新建與合并 讓我們來(lái)看一個(gè)簡(jiǎn)單的分支新建與分支合并的例子幽纷,實(shí)際工...
    Crisewng閱讀 526評(píng)論 0 0
  • 做個(gè)筆記https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF...
    未聞椛洺閱讀 266評(píng)論 0 0
  • 現(xiàn)在讓我們來(lái)看一個(gè)簡(jiǎn)單的分支與合并的例子式塌,實(shí)際工作中大體也會(huì)用到這樣的工作流程: 開(kāi)發(fā)某個(gè)網(wǎng)站。為實(shí)現(xiàn)某個(gè)新的需求...
    幸運(yùn)的小強(qiáng)本人閱讀 324評(píng)論 0 0