GIT合併
本節指令
git merge
git reset --hard ORIG_HEAD
git merge --no-ff
git tag
git tag -a -m
合久必分、分久必合。GIT在做分支控管時也是分分合合,這個單元就來講解怎麼做分支合併(merge)
。
一、分支合併
請先建立本單元的工作環境(分三次複製貼上):
mkdir merge1
cd merge1
git init
echo 1 > file1.txt
echo 1 > file2.txt
git add file1.txt
git commit -m "C1"
git add file2.txt
git commit -m "C2"
------------------------------
git checkout -b bug
echo 1 > file3.txt
git add .
git commit -m "C3"
echo 1 > file4.txt
git add .
git commit -m "C4"
------------------------------
git checkout master
echo 1 > file5.txt
git add .
git commit -m "C5"
echo 1 > file6.txt
git add .
git commit -m "C6"
master分支有以下檔案:
file1.txt、file2.txt、file5.txt、file6.txt
bug分支有以下檔案:
file1.txt、file2.txt、file3.txt、file4.txt
好啦!到目前為止,和上一節的檔案結構一樣,接著我要將bug合併到master分支上。
首先將分支切換到master:
git checkout master
接著將bug分支合併進來:
git merge bug
做完合併動作後,也代表bug分支的階段性任務完成,通常會將此分支刪除,執行:
git branch -d bug
因為bug分支已經合併過,用
-d
就能刪除,而不用-D
若不刪除分支,繼續留著也可以,就看你的決定了。
好啦!這樣就完成合併的動作了,來看一下分支圖:
這次的合併有幾個重點要看:
- 首先合併後GIT會自動多了一個提交(commmit)的版本,並自動加上說明
Merge branch bug
。 - 雖然合併了,但只有master往前推進一個版本(d6789aa),而bug分支還是繼續停留在原本的
C4
提交(commit)版本上。 - 在master分支查看資料夾檔案,一共有6個檔案:file1.txt~file6.txt
- 在bug分支查看資料夾檔案,一共有4個檔案:file1.txt~file4.txt
要解釋為何兩個分支的檔案有如此變化,我們把它畫成跟上個單元一樣的水流圖,這樣瞭解了吧!
補充:若你也想讓bug分支包含
C5
、C6
提交的file5.txt和file6.txt那就把master合併到bug分支裡就好啦,試看看吧!
結果如下:
二、回復合併
如果合併後,發現做錯了,想要反悔
怎麼辦呢?
git checkout master
git log --oneline
git reset --hard [C6的commit ID]
看吧!瑞凡,我們回去了~~
有更簡單的方法,可以利用ORIG_HEAD
別名直接回到上一版本
git reset --hard ORIG_HEAD
這裡reset指令中的--hard
表示強制將工作目錄(WD)的檔案回復到前一版本。
若你想返回前一版本,又要保留目前
工作目錄(WD)的檔案,可用--soft
,通常比較少用。
三、快轉(Fast-Forward)合併
請先建立本單元的工作環境(分二次複製貼上):
mkdir merge2
cd merge2
git init
echo 1 > file1.txt
echo 1 > file2.txt
git add file1.txt
git commit -m "C1"
git add file2.txt
git commit -m "C2"
------------------------------
git checkout -b hotfix
echo 1 > file3.txt
git add .
git commit -m "C3"
echo 1 > file4.txt
git add .
git commit -m "C4"
在master分支有以下檔案:
file1.txt、file2.txt
在hotfix分支有以下檔案:
file1.txt~file4.txt
由於master在C2
分出hotfix後,在hotfix繼續提交了C3
、C4
版本,因此hotfix停在C4
。
而master在分出hotfix後,就沒有再作業提交,因此還停在C2
。
此時,如果要將C3
、C4
版本做的變更合併至master裡,可下指令:
git checkout master
git merge hotfix
合併完後的命令提示及分支圖(請注意圖中Fast-Forward
這個字):
你會發現,分支圖和之前有不同之處:
- 並不像之前合併的樣子,有從旁分一個分支再合回來(長耳朵)
- 也沒有在合併後,多一個提交(commit)
這種情形我們稱為快轉合併(Fast-Forward)。會產生快進的情形,就是要合併進來的hotfix分支,剛好在master分支的前面,並沒有額外分叉出去,此時只要將master分支的指標往前移動
,就解決合併了,因此GIT做了Fast-Forward,省得麻煩還要再建commit
可是,如果想看到有長出耳朵的那種合併,怎麼做呢?
首先,我們復原剛才的合併,怎麼做還記得吧:
git reset --hard ORIG_HEAD
接著重做一次合併,但這次要加--no-ff
指令
git merge --no-ff hotfix
完成後,就長出耳朵來了:
四、衝突
到目前為止,合併好像做的滿順利的。但如果兩個分支都改了同一個檔案,就會造成衝突(conflict)
,很多人因為怕衝突,而不趕開分支,其實,在發生檔案衝突時,只要選擇你要保留哪一個版本的檔案內容,再來合併就解決啦!
所以衝突(conflict)是要人為來解決的,GIT沒有辦法幫你決定要哪個版本啊~~
請先建立本單元的工作環境(分三次複製貼上):
mkdir merge3
cd merge3
git init
echo 1 > file1.txt
echo 1 > file2.txt
git add file1.txt
git commit -m "C1"
git add file2.txt
git commit -m "C2"
------------------------------
git checkout -b release
echo 大家好 > file1.txt
echo 1 > file3.txt
git add --all
git commit -m "C3"
echo 1 > file4.txt
git add .
git commit -m "C4"
------------------------------
git checkout master
echo 我愛你 > file1.txt
echo 1 > file5.txt
git add --all
git commit -m "C5"
echo 1 > file6.txt
git add .
git commit -m "C6"
這兩個分支都改了file1.txt,release分支改成大家好
,而master分支改成我愛你
,接著我們將release合併到master裡,看會花生省魔術:
git checkout master
git merge release
慘了!慘了!發生衝突(Conflict),怎麼辦~怎麼辦~
我們先來看一下檔案狀態:
git status
這裡多了一個檔案狀態,稱做未合併(Unmerged paths
,簡單的說就是發生衝突(Conflict)啦!而且GIT會把file1.txt這個衝突檔案放在工作目錄(WD),讓你自己決定怎麼修改。
現在開啟sourceTree來解決衝突
有兩個選項可以選:
- Resolve using 'Mine':以主分支內容為主
- Resolve using 'Theirs':以副分支內容為主
所以如果選了Mine
,就會套用master分支的我愛你
選了Theirs
,就會套用release的大家好
選好後,執行git commit
就完成了。
如果你還是不知道要選Mine或Theirs,可能要先和別人多多討論,再來處理衝突,此時
你可以用以下指令先取消這次的合併:git reset --hard HEAD
五、標籤
輕量級的標籤:
git tag [標籤名稱]
含附註的標籤:
git tag -a [標籤名稱] -m "註解"
六、分支圖反解
又到了看圖說故事時間啦!這個單元多了分支合併,準備好挑戰了嗎?Let's go...
【Ex-304 分支圖練習】
【Ex-305 分支圖練習】
【Ex-306 分支圖練習】
【Ex-307 分支圖練習】
【Ex-308 分支圖練習】
七、Git Flow練習
實際上開發程式時,分支到底要怎麼規畫啊?Vincent Driessen提出了一套Git Flow開發流程A successful Git branching model
在sourceTree也有這項功能可以直接套用:
實際上我們只要懂得此流程,自己手動建分支也能達到同樣目的喔!以下條列出這些分支的特性及用途:
master:正式上線分支,合併(merge)最好要有專人負責。
develop:開發分支,提交(commit)、合併(merge)最好要有專人負責。
hotfix: 緊急修補分支,由master分支出來,可合併至master和develop,用途是解決正式版上線的bug。
feature:功能分支,由develop分支出來,可合併至develop,用途是開發新功能。
release:釋出版本分支,由develop分支出來,可合併至master和develop。用途是開發下一版本,也就是開發完成準備釋出時要建立。此分支只會針對該版本bug做修改及commit而已,但請不要在release繼續開子分支。
接下來,我們來分階段做好了,這樣比較單純些…
1、master上線分支、develop開發分支、feature功能分支
【Ex-309 Git Flow綀習】
feature流程:
git checkout -b feature develop →
git add →
git commit -m →
git checkout develop →
git merge feature (要不要耳朵隨便你) →
git branch -d feature (要不要砍隨便你)
※圖中並沒有將develop合併回merge,實務上是要的
做好的分支圖大概如下:
2、master上線分支、develop開發分支、feature功能分支、release釋出版分支
【Ex-310 Git Flow綀習】
release流程:
git checkout -b release develop →
git add →
git commit -m →
git checkout master →
git merge release →
git checkout develop →
git merge release (要不要耳朵隨便你) →
git branch -d release (要不要砍隨便你)
3、master上線分支、develop開發分支、feature功能分支、release釋出版分支、hotfix緊急修補分支
【Ex-311 Git Flow綀習】
hotfix流程:
git checkout -b hotfix master →
git add →
git commit -m →
git checkout master →
git merge hotfix (要不要耳朵隨便你) →
git checkout develop →
git merge hotfix (要不要耳朵隨便你) →
git branch -d hotfix →