1. 程式人生 > 程式設計 >詳解git merge命令應用的三種情景

詳解git merge命令應用的三種情景

一、git merge 命令應用的三種情景

1.1 “快進”(無衝突)

master分支

假設現在只有一個預設的 master 分支,並提交了3次,B0、B1和B2都是提交物件。

詳解git merge命令應用的三種情景

首先要清楚,每次產生的提交物件會包含一個指向上次提交物件(父物件)的指標,所以圖中B0、B1和B2之間的箭頭是指標指向父物件的意思,真正的提交順序還是B0到B1再到B2。同時 master 指標指向最新的提交B2。

另外Git中還有一個名為 HEAD 的特殊指標,它是一個指標,指向當前所在的本地分支(可以將 HEAD想象為當前分支的別名)。

dev新分支

現在新建一個分支並切換到新分支。

$ git checkout -b dev
Switched to a new branch 'dev'

它是下面兩條命令的簡寫:

$ git branch dev
$ git checkout dev

詳解git merge命令應用的三種情景

因為是在B2建立 dev,所以新分支 dev 指向B2。另外從分支 master 切換到分支 dev,所以HEAD指向當前分支 dev。

在 dev 分支工作並提交了2次:

詳解git merge命令應用的三種情景

合併dev和master

在分支 dev 的工作結束,切換到分支 master ,然後把 dev 合併到 master 上:

$ git checkout master
Switched to branch 'master'
$ git merge dev
Merge made by the 'recursive' strategy.
 test-2.txt | 3 ++-
 1 file changed,2 insertions(+),1 deletion(-)

由於當前 master 分支所指向的提交是你當前提交(dev的提交)的直接上游,所以 Git 只是簡單的將 master 指標向前移動。 換句話說,當你試圖合併兩個分支時,如果順著一個分支走下去能夠到達另一個分支,那麼 Git 在合併兩者的時候,只會簡單的將指標向前推進(指標右移),因為這種情況下的合併操作沒有需要解決的分歧——這就叫做 “快進(fast-forward)”。合併結果如下:

詳解git merge命令應用的三種情景

最後,你可以刪除 dev 分支,因為你已經不再需要它了 —— master 分支已經指向了同一個位置。 你可以使用帶 -d 選項的 git branch 命令來刪除分支:

$ git branch -d dev

1.2 非“快進”,修改不同檔案。(無衝突)

當在新分支 dev 進行了一次提交B3,再回到分支 master 又進行一次提交 B4。

詳解git merge命令應用的三種情景

這裡用 git merge 合併分為兩種情況,現在講第一種情況:

在 master 分支和 dev 分支的公共祖先 B2 後,master 和 dev 的提交是對不同檔案或者同一檔案的不同部分進行了修改,Git 可以合併它們。(比如說原來有 test-1 和 test-2 兩個檔案,B4修改的是 test-1 檔案,而B3修改的是 test-2 檔案,然後合併兩個分支。)

$ git checkout master
Switched to branch 'master'
$ git merge dev
Merge made by the 'recursive' strategy.
 test-2.txt | 3 ++-
 1 file changed,1 deletion(-)

合併是成功的。

出現這種情況的時候,Git 會使用兩個分支的末端所指的快照(B3 和 B4)以及這兩個分支的公共祖先(B2),做一個簡單的三方合併。注意這裡合併後 master 自動 commit 提交了一次,產生了提交B5。而B5中的結果是三方合併的結果。合併結果如下:

詳解git merge命令應用的三種情景

最後,合併完成,你已經不再需要dev分支了。 現在你可以刪除這個分支。

$ git branch -d dev

1.3 非“快進”,修改相同檔案。(有衝突)

當在新分支 dev 進行了一次提交B3,再回到分支 master 又進行一次提交 B4。

詳解git merge命令應用的三種情景

上面講的是第一種情況,現在講第二種情況:

在 master 分支和 dev 分支的公共祖先 B2 後,master 和 dev 的提交是對同一個檔案的同一個部分進行了不同的修改,Git 就沒法乾淨的合併它們。(比如說原來有 test-1 和 test-2 兩個檔案,B4修改的是 test-1 檔案,而B3修改的也是 test-1 檔案的同一部分,然後合併兩個分支。)

$ git checkout master
Switched to branch 'master'
$ git merge dev
Auto-merging test-1.txt
CONFLICT (content): Merge conflict in test-1.txt
Automatic merge failed; fix conflicts and then commit the result.

合併是失敗的。

此時 Git 做了合併,但是沒有自動地建立一個新的合併提交。 Git 會暫停下來,等待你去解決合併產生的衝突。 你可以在合併衝突後的任意時刻使用 git status 命令來檢視那些因包含合併衝突而處於未合併(unmerged)狀態的檔案:

$ git status
On branch master
You have unmerged paths.
 (fix conflicts and run "git commit")
 (use "git merge --abort" to abort the merge)

Unmerged paths:
 (use "git add <file>..." to mark resolution)

    both modified:  test-1.txt

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

任何因包含合併衝突而有待解決的檔案,都會以未合併狀態標識出來。 Git 會在有衝突的檔案中加入標準的衝突解決標記,這樣你可以開啟這些包含衝突的檔案然後手動解決衝突。 出現衝突的檔案會包含一些特殊區段,看起來像下面這個樣子:

This is test-1.
update test-1.
add test-1.
<<<<<<< HEAD
test master.
=======
test dev.
>>>>>>> dev

這裡 HEAD 表示所指示的版本(也就是你的 master 分支所在的位置,因為你在執行 merge 命令的時候已經檢出到了這個分支)在這個區段的上半部分(======= 的上半部分),而 dev 分支所指示的版本在 ======= 的下半部分。 為了解決衝突,你必須選擇使用由 ======= 分割的兩部分中的一個,或者你也可以自行合併這些內容。 例如,你可以通過把這段內容換成下面的樣子來解決衝突:

This is test-1.
update test-1.
add test-1.
test master.
test dev.

然後手動提交:

$ git add .
$ git commit -m "connection"
[master f7daa6b] connection

然後衝突就解決了。合併結果如下:

詳解git merge命令應用的三種情景

最後,合併完成,你已經不再需要dev分支了。 現在你可以刪除這個分支。

$ git branch -d dev

到此這篇關於詳解git merge命令應用的三種情景的文章就介紹到這了,更多相關git merge命令內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!