Git-入門教程(六)-分支管理
0.摘要
本文主要介紹Git的分支管理操作。
1.什麼是分支
從前面的內容可知,當我們建立了一個Git倉庫後會得到一個預設分支,叫做master,但只有一個分支顯然是不合適的。
比如:多人協作時,大家為了備份程式碼頻繁地將自己的程式碼提交到master分支中,這必然會造成大量的衝突,如果每個人都有一個獨立的分支,直到每個人的工作都結束後,再統一合併到master分支中,這樣就井然有序了。
或者:當你的專案已經被成功上線後卻出現了Bug,但這時候你卻在開發新的功能,Bug必須馬上修復,而現在的工作也需要進行儲存。你可以新建一個分支用於修復Bug,待Bug修復完畢後,將這一分支與主分支進行合併。然後,再切換到新功能開發的分支,繼續完成相應的工作。
2.建立並切換到新分支
方式一:
git branch #檢視當前已有分支
git branch dev #建立名為dev的分支
git checkout dev #切換到dev分支
方式二:我們也可以一條命令完成分支的建立和切換
git checkout -b dev
-b 引數表示:建立並切換到該新建分支。
完成分支建立與切換之後,我們再來看一下當前已有的分支:
git branch 會列出當前庫下存在的所有分支,並用 '*' 標記處當前分支。
從結果上看,我們已經成功建立並將dev切換為當前分支。
並且,此時dev分支上的內容與master分支上完全相同。
3.在新分支上進行一些工作併合併到主分支
首先,我們檢視一下目前dev分支下的 README.md檔案:
目前,dev分支下的README.md檔案只有一行,下面我們在該檔案下新增一行:
vim README.md #編輯README.md,新增一行內容
git add README.md #在dev分支下,add修改後的README.md
git commit -m "branch test" #在dev分支下,commit修改後的README.md
通過檢視新的README.md檔案可以看出內容已修改:
4.將dev分支合併到master分支並刪除dev分支
當我們在dev分支下完成了相應的工作,就需要把該分支merge到master分支上,這樣別人才能看到我們所做的修改。
git checkout master #切換到主分支
git branch #檢視是否切換成功,如果'*'標記在master分支前就表示切換成功
git merge dev #把dev分支合併到master分支上
git branch -d dev #刪除dev分支
git branch #檢視是否刪除dev分支
cat README.md #檢視README.md內容
檢視結果我們發現,我們已經成功刪除了dev分支,並且在dev分支下的新增的內容也成功合併到了master分支下。
5.分支衝突
在分支合併的過程中,往往並不像上面那麼順利,可能會存在衝突的問題。下面,我們就用例項模擬一下分支衝突的問題。
step1:新建檔案並commit
vim mission.txt #新建一個檔案,並填入以下內容:
#[progress]:
#mession1:
#mession2:
git add mission.txt
git commit -m "first commit"
step2:新建分支dev1,並對mission.txt進行修改
git checkout -b dev1 新建分支dev1
vim mission.txt #修改檔案,內容如下
#[progress]:
#mession1: completed by dev1
#mession2:
git add mission.txt
git commit -m "dev1 has completed mission1"
git checkout master
step3:新建分支dev2,也對mission.txt進行修改
git checkout -b dev2 新建分支dev2
vim mission.txt #修改檔案,內容如下
#[progress]:
#mession1:
#mession2: completed by dev2
git add mission.txt
git commit -m "dev2 has completed mission2"
git checkout master
step4:將dev1,dev2與master合併
git merge dev1 #合併分支dev1
git merge dev2 #合併分支dev2
下面,重點來了:
由於兩個分支都對mission.txt進行了修改,並且分別修改了不同的部分,這時候就產生了衝突。因為,Git也不知道究竟該聽誰的了,所以“友善地”提醒了您fix好衝突之後再merge。
這種情況並不是特例,在多人協作時需要格外注意。當兩位開發人員同時建立了自己的分支並獨立開展工作,但由於之前沒商量好,同時對某一檔案進行了修改。那麼在merge的時候,必然有一位需要解決衝突問題。
6.分支衝突解決
解決衝突只能依靠人工修改。如果其他人只是多敲了一個空格,你只需要在你的檔案對應位置不上空格即可。但如果衝突的地方很多,那麼工作量就非常大,這也就是為什麼提醒讀者在一定要注意這個問題的原因。多人合作完成任務的時候,一定要對檔案有明確的劃分。
下面,我們介紹如何查詢衝突。發現問題才能解決問題嘛。
git status #幫助我們定位衝突的檔案
Git告訴我們,衝突的檔案是mission.txt,它被重複編輯。
此時,我們顯示一下該檔案的內容:
cat mission.txt
我們可以看到衝突的地方,Git已經使用<<<<<<<,=======,>>>>>>>幫我們分隔開來。並且,我們還能看出衝突內容所在的分支。
解決的方法就是直接在master分支下編輯mission.txt檔案並儲存,至於修改成什麼樣子,那就完全認為決定了,即便是刪除了素有內容,Git也不會報錯。
修改完檔案後,在master下add+commit,之後刪除分支:
git add mission.txt #add檔案
git commit -m "fix comflict" #提交檔案
git branch -d dev1 #刪除分支dev1
git branch -d dev2 #刪除分支dev2
這裡留個小問題,如果我們把mission.txt中,每一行之間都新增一個空行,那麼就不會出現分支衝突的問題,比如:
初始的mission.txt為:
dev1分支下修改的mission.txt為:
dev2分支下修改的mission.txt為:
當我們在master分支下執行:
git merge dev1 #合併分支dev1,順利merge
git merge dev2 #合併分支dev2,需要新增merge說明,但也可以merge
除了合併dev2需要新增說明外,並不會產生衝突:
merge結束後,兩個分支的內容都成功merge到master下了:
原因是:
如果不同分支同時更改了同一檔案的同一文字塊,這時候會產生衝突;
如果不同分支同時更改了同一檔案的不同一文字塊,這時候不會產生衝突;
如果兩個分支修改的內容,中間有空行,那麼就屬於不同文字塊,自然也就不衝突了。
7.Fast forword 模式
在上述的merge過程中,我們會看到一個關鍵詞叫做:Fast Forword,下面解釋一下Fast Forword的含義和用法:
為了直觀理解兩者的差別,打個比方(為避免例子過於臃腫,這個例項不過分深究Git的細節):
有三個人分別叫:master、dev1、dev2。首先master有一份問卷,dev1影印了一份問卷並填寫,之後就直接把問卷交給了master;dev2也影印了一份問卷並填寫,但dev2不願意把問卷直接給master,所以master只能把問卷的答案抄下來帶走;
由於master可以直接拿走dev1填好的問卷,所以回收問卷很快捷,這就是Fast Forword;
由於master不能拿走dev2的問卷,只能多花點時間把答案抄下來,所以回收問卷很慢,這就是No-Fast Forword;
總結一下:
Fast Forword:當前分支合併到另一分支時,在沒有衝突的情況下,Git直接移動檔案指標到當前分支,這個過程叫做Fast Forward。
比如,我們新建了一個分支dev1,並使用Fast Forward合併到master下:
HEAD同時指向了master和dev1兩個分支,Git中出現這種情形的唯一可能就是master和dev1目前是同一個分支。
No-Fast Forword:當前分支合併到另一分支時,如果在merge時生成一個新的commit,這個過程叫做No-Fast Forward。
比如,我們新建了一個分支dev2,並使用--no-ff引數合併到master下:
需要說明的是,由於--no-ff方式需要新建commit,因此在合併的時候,需要新增commit說明:
git merge --no-ff -m "merge with no-ff " dev2
那麼,Fast Forword和No-Fast Forword有什麼區別呢?
兩者主要在檢視git log資訊方面有差別:
Fast Forword沒有新建commit,合併後的沒有歷史有分支,看不出來曾經做過合併。
No-Fast Forword新建commit,合併後的歷史有分支,能看出來曾經做過合併。