天天看點

git入門五(分支合并沖突和衍合)

分支合并沖突的處理

合并分支的沖突時在不同的分支中修改了同一個檔案的同一部分,程式無法把兩份有差異的檔案合并,這時候需要人為的幹預解決沖突。目前處于master 分支,當dev 分支和master 分支對相當部分test1.txt 都做了修改,當合并dev 分支的時候,合并會出現分支沖突如下:查詢目前工作區的狀态可以顯示那些檔案發生合并沖突,任何包含未解決沖突的檔案都會以未合并(ummerged)的狀态列出,git 會加入标準沖突解決标記,可以通過手工定位來解決這些沖突。可以看大 =======隔開以上部分就是目前活動分支,也是合并的基準分支(head 指向的master分支),======分隔符以下的是dev分支中的内容。解決沖突的辦法無非是二者選其一或者由你親自整合到一起。比如你可以兩部分内容合并成 一部分内容。

$ git branch

  dev

* master

  testing

$ git merge dev

Auto-merging test1.txt

CONFLICT (content): Merge conflict in test1.txt

Automatic merge failed; fix conflicts and then commit the result.

$ git status

# On branch master

# Unmerged paths:

#   (use "git add/rm <file>..." as appropriate to mark resolution)

#

#       both modified:      test1.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ notepad test1.txt

<<<<<<< HEAD

now this is bug fix branch

=======

this is branch merge conflict problem

>>>>>>> dev

同時還可以用圖形化界面的工具來處理分支,git mergetool 指令會調用時目前系統配置的合并工具。合并完成後可以查詢狀态git status 來确認所有沖突都已經解決。如果沖突解決都已完成,可以把合并後的内容送出到暫存區,可以用git commit 完成這次合并送出。針對沖突合并,需要寫好注釋說明,後續檢視會更加簡單友善。

$ git commit -m "master merge dev branch"

[master 05a2f29] master merge dev branch

 1 files changed, 4 insertions(+), 1 deletions(-)

分支的管理

git branch 是查詢目前所有分支的清單,*号的表示目前的活動分支,也就是目前所在的分支。也就是說如果現在有送出更新,目前的工作分支master 分支或向前移動。若要看各個分支最後一個送出對象的新,可以通過git branch -v 來檢視。

$ git branch -v

  dev     be70ec8 dev

* master  05a2f29 master merge dev branch

  testing 0c8f2de testing branch change

在所有分支清單中,可以篩選出那些與目前分支尚未合并,通過參數--merge 可以篩選出那些分支在目前分支的上遊,這些分支隻需要通過fast-forward 移動指正就可以移動當目前最後送出給對象。--no-merged 可以檢視還位和目前分支合并的分支。如dev分支和目前分支還未合并。如果以前是無效的分支,可以通過git branch -d 删除制定的分支。

$ git branch --merged

$ git branch --no-merged

$ git branch -d testing

Deleted branch testing (was 0c8f2de).

長期分支

git隻是簡單的三方合并分支的特性,是以在腳長的一段時間内,把多個分支合并到一個分支或者同時擁有多發分支進行開發。由于每個分支都有特定的任務,随着開發的推進,随時可以把某個特性分支合并到其它分支中。需求使用git 的開發者都喜歡用這種方式開發,一般來說僅僅在master 分支保留穩定的代碼,就是已經釋出或者經過測試的代碼。與此同時,你可以同時擁有多個開發分支。每個開發分支都有特定的任務。如還有一個叫develop 的平行分支,專門擁有後續的開發,僅擁有穩定性的測試。一旦到達某種穩定的狀态就可以合并到master 分支。如果有其它特性的短缺分支能夠通過測試,并且不會引如更多錯誤後,就可以并到主幹master分支中。等待下一次釋出。

随着送出對象的不斷右移指針,穩定分支總是在送出曆史中落後一大截,而且前言分支總是比較靠前。穩定分支總是滞後,經過測試比較穩定的對象或者集合才被合并到穩定的分支上。這樣可以維護不同層次的穩定。

特性分支

在任何規模的項目中可以使用特性分支(topic).一個特性是指一個短期的,用來實作單一特性與其相關的工作分支,你可以在以前版本中從未做過類似的這樣事情,因為建立和合并分支的消耗太大。然而在git中,一天之内建立,删除和合并多個分支是常見的事情。在建立特性分支後,你可以送出合并到主幹分支,然後删除他,該技術讓你迅速且完全進行語境切換。因為你的工作分散在不同的流水性力,每個分支力改變都和他的目标特性相關。你可以把做出的改變保持在特性分支幾分鐘。幾天甚至幾個月。等他們成熟以後再合并。而不用在乎他們建立的順序和進度。

一般分支都是在本地。大部分都是本地分支。這一點很重要。目前使用合并分支的時候,一切都在你的git 倉庫中進行的,完全不與伺服器互動。隻有當你有固定的分支或者分享需要和其它合作夥伴共享的時候,才需要推送到中心伺服器。

遠端分支:

remote branch 是對遠端倉庫中的分支的索引。他們是無法移動本地分支。隻有在git進行網絡互動時才會更新。遠端分支就是書簽,提醒着你上次連結遠端倉庫時上面各個分支的位置。 我們用倉庫名/分支名 這樣的形式表示遠端分支。比如我們想想上次同 origin 倉庫進行通訊時master 分支的樣子。就應該檢視origin/master 分支。如果你和同伴一起修複某個問題。他們推送一個iss53分支到遠端倉庫。雖然你可能也有一個本地的iss53分支,但指向伺服器上最新的更新的英是origin/iss53分支。

假如團隊中心伺服器git位址:git.ourcompany.com.。如果你從這裡克隆,git會自動在為你将次遠端倉庫嗎命名為origin。并下載下傳其中的資料,建立一個指向它的master分支指針。在本地命名為Origin/master。但你無法再本地更改資料,接着git建立一個屬于你自己本地的master分支。始于origin上master分支相同的位置。如下圖

git入門五(分支合并沖突和衍合)

如果你在本地master 分支做了些改動。與此同時本地分支向前推進。隻要本地沒有向遠端伺服器推送,origin/master 分支指針任然保持在原位不會移動。

git入門五(分支合并沖突和衍合)

在本地工作同時有人向遠端倉庫推送内容會讓曆史開始分流。可以允許git fethch origin 來同步遠端伺服器上的資料到本地。該指令首先找到origin 是哪個伺服器。從上面擷取你未擁有的資料。更新你本地的資料庫。然後把Origin/master的指針移動到他最新的位置上。

git入門五(分支合并沖突和衍合)

如果有多個遠端分支的項目是如果進行工作的。我們假設你還有另外一個内部使用的遠端伺服器。通過git remote add 指令吧它加為目前項目的遠端分支之一。我們把它命名為teamtone,以便代替完整的git url。

git入門五(分支合并沖突和衍合)

現在把另外一個遠端伺服器添加為遠端倉庫了,現在可以用git fetch teamtone 來擷取小組伺服器你還沒有的資料,由于目前伺服器的内容是origin伺服器上的子集,git不會下載下傳任何資料。而隻是簡答建立一個名為teamone/master 的遠端分支。指向teamone 伺服器上master 分支所有在的送出對象 31b3e 如下圖:現在你在本地就有了一個指向teamone 的索引。

推送本地分支

要想和其它人分享某個本地的分支,你需要把它推送到一個擁有些權限的遠端倉庫。你建立的本地分支部會因為你的寫入操作而被自動同步到你引入的遠端伺服器上,你需要明确的執行推送分支的操作。換句話說,對于無意分享的分支,你盡管保留私人分支好了。而隻推送那些協同工作要用到的特性分支。如果有個交severfix 的分支需要和他人一起開發,可以運作git push (遠端倉庫名) 分支名。

$ git push origin serverfix

Total 0 (delta 0), reused 0 (delta 0)

To [email protected]:andy/test.git

 * [new branch]      serverfix -> serverfix

git 自動把serverfix 分支名擴充為refs/heads/serverfix:refs/heads/serverfix,意思是“取出我在本地的serverfix分支,推送到遠端倉庫的serverfix分支中區,一般在同一分支上可以省略, git push origin serverfix:serverfix,還可以把本地分支推送到遠端不同的分支。可以用已經存在的新遠端分支或新的遠端分支。

當你再次從遠端擷取伺服器上資料的時候,同伴會擷取到origin/serverfix 和 origin/newfix 的分支,并指向伺服器上serverfix 所指向的版本。在fetch操作下載下傳好新的遠端分支之後。你任然無法再本地編輯遠端倉庫中的分支。換句話說你不會有一個新的serverfix 分支。有的隻是一個你無法移動的Origin/serverfix指針。你如果需要把該遠端分支的内容合并到目前分支,可以運作git merge origin/serverfix ,如果想要一份自己的serverfix來開發。可以在遠端分支的基礎上分化一個新的分支來。這會切換到新的serverfix 的本地分支。其内容同遠端分支 origin/serverfix 一緻。這樣可以繼續開發了。

$ git push origin serverfix:newfix

To [email protected]:andyi/test.git

 * [new branch]      serverfix -> newfix

$ git fetch origin

remote: Counting objects: 19, done.

remote: Compressing objects: 100% (7/7), done.

remote: Total 17 (delta 6), reused 16 (delta 5)

Unpacking objects: 100% (17/17), done.

From github.com:andyi/test

 * [new branch]      dev        -> origin/dev

   894ed8b..37b40ce  master     -> origin/master

跟蹤遠端分支

 從遠端分支checkout 出來的本地分支。稱為跟蹤(tracking branch),跟蹤分支是一種和某個遠端分支有直接聯系的本地分支。在跟蹤分支裡輸入git push,git 會自行推斷應該向那個伺服器的那個分支推送資料。同樣,在這些分支裡運作git pull 會回去遠端索引,并把它們的資料合并到本地分支中。

 在克隆倉庫時,git 通常會自建立一個名master 的分支來跟蹤,這正是git push 和 git pull 一開始就能正常工作的原因。當然,你可以随心所欲設定其為跟蹤分支,比如在origin 上除了master 之外的其它分支。剛才我們已經開到了這樣的一個例子。 git checkout -b 分支名  遠端名/分支名, 還可以用 --track  選項。 如果本地分支和遠端分支的名稱不一樣,可以本地分支換個名稱。

$ git checkout -b serv origin/serverfix

Branch serv set up to track remote branch serverfix from origin.

Switched to a new branch 'serv'

  master

* serv

  serverfix

删除遠端分支

如果不再需要摸個遠端分支了,比如搞定某個特性并合并進了遠端的master 分支(或任何其他存放穩定的代碼分支),可以用這個指令 git push 遠端名:分支名。如果運作這個指令,伺服器上的分支就沒了,git puhs 遠端名 本地分支:遠端分支 文法,如果省略本地分支。那就是等提前空白然後把它變成遠端分支。

分支的衍和

把一個分支中的修改整合到另一個分支的辦法由兩種:merge 和 rebase(翻譯為衍合)。

基本的衍合操作,當開發程序分叉到兩個不同的分支,有各自送出了更新。最簡單的整合方式是合并merege 指令。他會把兩者共同的祖先ac631f6進行三方合并。并合後産生一個結果就是兩條分的合并點。

git入門五(分支合并沖突和衍合)

其實除了合并以外,還有另外一個選擇,可以把7599941産生變化的更新檔在4632de基礎上重新打一遍。在git 裡着叫衍合(rebase),有了rebase指令,就可以在把在一個分隻裡送出的改變移動到另一個分支重方一遍。他們的原理是回到兩個分支最近共同的祖先。根據目前分支(也就是要進行衍合的分支)後續曆次送出的對象在這裡分支隻有一個送出。生産一系列檔案更新檔,然後基地分支(也就是主幹分支master 的最後一個送出對象為新的出發點,逐個應用之前準備好的更新檔檔案,最後會生産一個新的合并送出對象。進而改寫需要衍合分支的送出曆史。使他成為master 分支的直接下遊。

git入門五(分支合并沖突和衍合)