1. 程式人生 > >Git-入門教程(六)-分支管理

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,合併後的歷史有分支,能看出來曾經做過合併。