git學習系列(三)---- 分支的合併(git merge)與變基(git rebase)

最近在學習git,對git也有了新的認識,寫一些總結,文章基本總結於 Pro Gitcss

其餘git相關文章:html

git學習系列(一)---- git的基礎知識
git學習系列(二)---- git的分支git

本章主要介紹分支的合併與變基,分支的基礎知識在上一章已經講述過了。vim

注:圖片中的箭頭方向指向的是上一次提交(父對象),因此實際的提交順序是從左往右。segmentfault

合併(git merge)

首先咱們來構建一個工做流程學習

1.首先,咱們假設你正在你的項目上工做,而且已經有一些提交spa

clipboard.png

2.這個時候你須要開發一個新功能,你建立分支issue53並切換至他指針

git checkout -b iss53

3.你修改了一些東西,並作了提交(commit)code

vim index.html
 git commit -a -m 'added a new footer [issue 53]'

clipboard.png

4.這時候你發現有個線上問題須要你緊急處理,因此你先切回master,並新建一個緊急分支hotfix,在hotfix上進行了修改htm

git checkout master
git checkout -b hotfix
vim index.html
git commit -a -m 'fixed the broken email address'

clipboard.png
5.問題已經解決,這個時候須要合併到master上線

git checkout master
git merge hotfix

clipboard.png

在合併的時候,你應該注意到了"快進(fast-forward)"這個詞。 因爲當前 master 分支所指向的提交是你當前提交(有關hotfix 的提交)的直接上游,因此 git 只是簡單的將指針向前移動。
換句話說,當你試圖合併兩個分支時,若是順着一個分支走下去可以到達另外一個分支,那麼 git在合併二者的時候,只會簡單的將指針向前推動(指針右移),由於這種狀況下的合併操做沒有須要解決的分歧——這就叫作「快進(fast-forward)」。

6.這個時候你能夠返回issue53分支繼續你的工做

git checkout iss53
vim index.html
git commit -a -m 'finished'

clipboard.png
你在 hotfix 分支上所作的工做並無包含到 iss53 分支中。 若是你須要拉取 hotfix 所作的修改,你可使用 git merge master 命令將 master 分支合併入 iss53 分支,或者你也能夠等到 iss53 分支完成其使命,再將其合併回 master 分支。

7.issue53工做已經完成,你想要合併到master上

git checkout master
git merge iss53

這和你以前合併 hotfix 分支的時候看起來有一點不同。 在這種狀況下,你的開發歷史從一個更早的地方開始分叉開來(diverged)。
由於,master 分支所在提交併非 iss53 分支所在提交的直接祖先,git 不得不作一些額外的工做。
出現這種狀況的時候,git 會使用兩個分支的末端所指的快照(C4 和 C5)以及這兩個分支的工做祖先(C2),作一個簡單的三方合併。

clipboard.png

和以前將分支指針向前推動所不一樣的是,git 將這次三方合併的結果作了一個新的快照而且自動建立一個新的提交指向它。這個被稱做一次合併提交

clipboard.png

8.遇到衝突時的解決方案
上述的操做是在沒有衝突的狀況下進行的,git會自動爲你合併,並生成一個新的快照。然而當兩個不一樣的分支對同一文件作了不一樣的修改,git就無能爲力了,此時 git 作了合併,可是沒有自動地建立一個新的合併提交,須要你本身去解決合併後的衝突,生成新的commit,而後再提交就能夠了。

git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

查看已合併分支與未合併分支

git branch --merged
git branch --no-merged

變基(get rebase)

在 git 中整合來自不一樣分支的修改主要有兩種方法:merge 以及 rebase
請回顧以前在 分支的合併 中的一個例子,你會看到開發任務分叉到兩個不一樣分支,又各自提交了更新。

clipboard.png

你能夠提取在 C4 中引入的補丁和修改,而後在 C3 的基礎上應用一次。 在 Git 中,這種操做就叫作 變基。 你可使用 rebase 命令將提交到某一分支上的全部修改都移至另外一分支上,就好像「從新播放」同樣。

git checkout experiment
git rebase master

原理
1.首先找到這兩個分支(即當前分支 experiment、變基操做的目標基底分支 master)的最近共同祖先 C2
2.對比當前分支相對於該祖先的歷次提交,提取相應的修改並存爲臨時文件
3.而後將當前分支指向目標基底 C3
4.最後以此將以前另存爲臨時文件的修改依序應用

如今回到 master 分支,進行一次快進合併。

git checkout master
git merge experiment

clipboard.png
此時,C4' 指向的快照就和上面使用 merge 命令的例子中 C5 指向的快照如出一轍了。
這兩種整合方法的最終結果沒有任何區別,可是變基使得提交歷史更加整潔。
你在查看一個通過變基的分支的歷史記錄時會發現,儘管實際的開發工做是並行的,但它們看上去就像是串行的同樣,提交歷史是一條直線沒有分叉

假如在rebase時遇到衝突了該怎麼解決

clipboard.png

git自己會給出你下一步的提示,這時候你只須要打開衝突的文件,解決完衝突以後

git add .
git rebase --contine

注:合併與變基雖然操做過程有差別,但最終你指向的快照是相同的
解決衝突時,新的修改會存儲在補丁當中,即C4‘

原本還想着寫一下變基可能會帶來的風險與問題,可是本篇的篇幅已經有點長了,那就放在下一章講述吧

相關文章
相關標籤/搜索