首頁  >  文章  >  開發工具  >  Git學習之了解git merge指令

Git學習之了解git merge指令

青灯夜游
青灯夜游轉載
2022-03-18 19:48:593435瀏覽

這篇文章帶大家了解學習Git分支,介紹一下使用分支的Git Merge指令,希望對大家有幫助!

Git學習之了解git merge指令

在Git中merge是用來把分叉的提交歷史放回一起的方式。 git merge指令用來將你先前使用git branch指令建立的分支以及在此分支上獨立開發的內容整合為一個分支。

請注意下面的所有指令都會是將其他分支合併到目前所在工作分支上。目前工作分支的內容會因為merge操作產生更新,但是目標分支則完全不受影響。再次強調,這意味著git merge通常與其他幾個git命令一起使用,包括使用git checkout命令來選擇當前工作分支,以及使用git branch -d指令來刪除已經合併過的廢棄分支。

它是如何運作的

git merge會將多個提交序列合併進一個統一的提交歷史。在最常見的使用場景中,git merge被用來合併兩個分支。在本文檔接下來的部分,我們將專注於此合併場景。在這種場景中,git merge接受兩個commit指針,通常是兩個分支的頂部commit,然後向前追溯到這兩個分支最近的一個共同提交。一旦找到這個共同提交,Git就會建立一個新的"merge commit",用來合併兩個分支上各自的提交序列。

比如說我們有一個功能分支由main分支衍生出來,現在我們希望將這個函數分支合併回main分支。

Git學習之了解git merge指令

執行合併指令會將指定分支合併到目前工作分支上,我們假設目前工作分支為main。 Git根據兩個分支自行決定合併提交的演算法(將在下面具體討論)。

Git學習之了解git merge指令

合併commit與普通commit不一樣,因為合併commit會有兩個父提交。建立一個合併commit時Git會嘗試自動將兩個獨立的提交歷史合併為一個。不過當Git發現某一塊資料在兩邊的提交歷史中都含有變更,它將無法自動合併。這種情況稱為版本衝突,此時Git需要人為介入調整才能繼續合併。

準備合併

在實際進行合併作業之前,需要進行一些準備步驟,以確保合併過程能夠順利進行。

確認接收合併的分支

執行git status指令查看目前分支的狀態,確保HEAD指正指向的是正確的接收合併的分支。如果不是,執行git checkout指令切換到正確的分支。在我們的範例中,執行git checkout main

取得最新的遠端提交

確保合併作業所涉及的兩個分支都更新到遠端倉庫的最新狀態。執行git fetch拉取遠端倉庫的最新提交。一旦fetch操作完成,為了保證main分支與遠端分支同步,還需執行git pull指令。

合併

當上述的準備工作都已完備,合併就可以正式開始了。執行git merge <branch></branch>指令,其中為需要合併到目前分支的目標分支名稱。

快轉合併

目前工作分支到合併目標分支之間的提交歷史是線性路徑時,可以進行快轉合併。在這種情況下,不需要真實的合併兩個分支,Git只需要把目前分支的頂端指標移到目標分支的頂端就可以了(也就是快轉的意思)。在這種情況下快轉合併成功的將提交歷史合併至一處,畢竟目標分支中的提交此時都包含在當前分支的提交歷史中了。對於將功能分支快轉合併到main分支的流程可以參考下圖所示:

Git學習之了解git merge指令

然而快轉合併在兩個分支出現分叉的情況下是不允許執行的。當目標分支相對於目前分支的提交歷史不是線性的,Git只能透過三路合併演算法來決定如何對兩個分支進行合併。三路合併演算法需要使用一個專用commit來整合兩邊的提交歷史。這個名詞源自於Git要想產生合併commit,需要用到三個commits:兩個分支的頂端commit,以及它們的共同祖先commit。

Git學習之了解git merge指令

雖然實際上可以選擇使用這些不同的合併策略,但是大多數開發者更喜歡快轉合併(透過利用rebasing 指令),尤其是用於小功能的開發或bug修復;反之對於合併長期開發的功能分支,則更傾向於使用三路合併的方式。在第二種場景中,merge產生的合併commit會作為兩個分支合併的標誌保留在提交歷史中。

接下來我們用下面第一個例子來展示如何進行快轉合併。下面的指令會先建立一個新分支,在新分支上進行兩次提交,然後用快轉合併把新分支合併回main分支。

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

這個例子中的工作流程通常用於短期功能的開發,這種開發流程更多地被當做是比較獨立的一次開發流程,與之對應的則是需要協調和管理的長期功能開發分支。

另外還需注意到,在此例中Git不會對git branch -d指令發出警告,因為new-feature的內容已經合併到主分支裡了。

在某些情況下,雖然目標分支的提交歷史相對於當前分支是線性的,可以進行快進合併,但你仍然希望有一個合併commit來標誌合併在此commit發生過,那麼可以在執行git merge指令時使用--no-ff選項。

git merge --no-ff <branch>

以上指令將指定分支合併到目前分支,但總是會產生一個合併commit(即便這項合併作業可以快轉)。當你需要在倉庫的提交歷史中標記合併事件時這一命令相當有用。

三路合併

接下來的例子與上面比較像,但是因為main分支在feature分支向前發展的過程中,自身也發生的改變,因此在合併時需要進行三路合併。在進行大的功能開發或有多個開發者同時進行開發時這種場景相當常見。

Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

需要注意在這種情況下,由於沒有辦法直接把main的頂端指標移到new-feature分支上,因此Git無法執行快轉合併。

在大多數實際工作場景中,new-feature應該是一個很大的功能,開發過程持續了相當長的時間,這也就難免同時期在 main分支上也有新的提交。如果你的功能分支大小像上面的範例一樣小,則完全可以使用rebase將new-feature分支變基到main分支上,然後再執行一次快轉合併。這樣也會避免在專案提交歷史中產生過多的冗餘。

解決衝突

如果將要合併的兩個分支都修改了同一個而檔案的同一個部分內容,Git就無法確定應該使用哪個版本的內容。當這種情況發生時,合併過程會停止在合併commit提交之前,以便給用戶留下機會​​手動修復這些衝突。

在Git的合併過程中,很棒的一點是它使用人們熟知的 編輯 / 暫存 / 提交 這樣的工作流程來解決衝突。當碰到合併衝突時,執行git status指令會列出哪些檔案含有衝突並需要手動解決。例如當兩個分支都修改了hello.py檔案的同一部分,你會看到類似下面這樣的資訊:

On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py

衝突是如何顯示的

當Git在合併過程中碰到了衝突,它會編輯受影響的文件中的相關內容,並添加視覺標記用以展示衝突中雙方在此部分的不同內容。這些視覺標示為:>>>>>>。要找到衝突發生的具體位置,在文件中搜尋這些視覺標記會非常方便地達成目的。

here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

通常來說在 ====== 標記之前的內容來自於接收合併的分支,而在這之後的內容來自於要合併的分支。

一旦找到衝突的部分,就可以依照需求來修正衝突。當你完成了衝突的修復並準備好繼續進行合併,只需要執行git add指令把已經解決好衝突的檔案加入暫存區,告訴Git這些衝突已經解決完畢即可。這之後就像正常提交程式碼一樣執行git commit完成合併commit。這個過程跟正常情況下提交程式碼是完全一樣的,也就是說對一般開發者來說處理衝突也是小菜一碟。

也需注意合併衝突只可能出現在三路合併過程中,在快轉合併中不會出現衝突。

總結

本文是關於git merge指令的概覽。在使用Git的過程中,合併是非常重要的操作。本文討論了合併操作背後的機制,以及快轉合併與三路合併的差異。需要讀者記住的要點如下:

  • Git 合併流程是把不同的提交序列合併到一個統一的提交歷史中

  • ##Git合併過程中有兩個主要的方式:快轉合併和三路合併

  • 除非兩個提交序列中出現衝突,Git通常可以自動對提交進行合併

推薦學習:《

Git教學

以上是Git學習之了解git merge指令的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除