GIT 分支管理:創建與合並分支、解決合並沖突


分支就是科幻電影里面的平行宇宙,當你正在電腦前努力學習Git的時候,另一個你正在另一個平行宇宙里努力學習SVN。

如果兩個平行宇宙互不干擾,那對現在的你也沒啥影響。不過,在某個時間點,兩個平行宇宙合並了,結果,你既學會了Git又學會了SVN!

分支在實際中有什么用呢?假設你准備開發一個新功能,但是需要兩周才能完成,第一周你寫了50%的代碼,如果立刻提交,由於代碼還沒寫完,不完整的代碼庫會導致別人不能干活了。如果等代碼全部寫完再一次提交,又存在丟失每天進度的巨大風險。

現在有了分支,就不用怕了。你創建了一個屬於你自己的分支,別人看不到,還繼續在原來的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到開發完畢后,再一次性合並到原來的分支上,這樣,既安全,又不影響別人工作。

其他版本控制系統如SVN等都有分支管理,但是用過之后你會發現,這些版本控制系統創建和切換分支比蝸牛還慢,簡直讓人無法忍受,結果分支功能成了擺設,大家都不去用。

但Git的分支是與眾不同的,無論創建、切換和刪除分支,Git在1秒鍾之內就能完成!無論你的版本庫是1個文件還是1萬個文件。

創建與合並分支

在版本回退里,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git里,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是當前分支。

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點:

每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也越來越長:

當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:

你看,Git創建一個分支很快,因為除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!

不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次后,dev指針往前移動一步,而master指針不變:

假如我們在dev上的工作完成了,就可以把dev合並到master上。Git怎么合並呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合並:

所以Git合並分支也很快!就改改指針,工作區內容也不變!

合並完分支后,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉后,我們就剩下了一條master分支:

真是太神奇了,你看得出來有些提交是通過分支完成的嗎?

下面開始實戰。

首先,我們創建dev分支,然后切換到dev分支:

$ git checkout -b dev Switched to a new branch 'dev'

git checkout命令加上-b參數表示創建並切換,相當於以下兩條命令:

$ git branch dev $ git checkout dev Switched to branch 'dev'

然后,用git branch命令查看當前分支:

$ git branch * dev master

git branch命令會列出所有分支,當前分支前面會標一個*號。

然后,我們就可以在dev分支上正常提交,比如對readme.txt做個修改,加上一行:

create new branch dev..

然后提交:

$ git add readme.txt $ git commit -m "create new branch...." [dev 45ae9a9] create new branch.... 1 file changed, 1 insertion(+)

現在,dev分支的工作完成,我們就可以切換回master分支:

$ git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'.

切換回master分支后,再查看一個readme.txt文件,剛才添加的內容不見了!因為那個提交是在dev分支上,而master分支此刻的提交點並沒有變:

現在,我們把dev分支的工作成果合並到master分支上:

$ git merge dev Updating 90bc1f7..45ae9a9 Fast-forward readme.txt | 1 +
 1 file changed, 1 insertion(+)

git merge命令用於合並指定分支到當前分支。合並后,再查看readme.txt的內容,就可以看到,和dev分支的最新提交是完全一樣的。

注意到上面的Fast-forward信息,Git告訴我們,這次合並是“快進模式”,也就是直接把master指向dev的當前提交,所以合並速度非常快。

當然,也不是每次合並都能Fast-forward,我們后面會講其他方式的合並。

合並完成后,就可以放心地刪除dev分支了:

$ git branch -d dev Deleted branch dev (was 45ae9a9).

刪除后,查看branch,就只剩下master分支了:

$ git branch * master

因為創建、合並和刪除分支非常快,所以Git鼓勵你使用分支完成某個任務,合並后再刪掉分支,這和直接在master分支上工作效果是一樣的,但過程更安全。

小結

Git鼓勵大量使用分支:

查看分支:git branch

創建分支:git branch <name>

切換分支:git checkout <name>

創建+切換分支:git checkout -b <name>

合並某分支到當前分支:git merge <name>

刪除分支:git branch -d <name>

解決沖突

人生不如意之事十之八九,合並分支往往也不是一帆風順的。

准備新的feature1分支,繼續我們的新分支開發:

$ git checkout -b feature1 Switched to a new branch 'feature1'

 

修改readme.txt最后一行,改為:

create new branch feature1..

 

feature1分支上提交:

$ git add readme.txt $ git commit -m "create new branch feature1 first modify" [feature1 b4309b0] create new branch feature1 first modify 1 file changed, 1 insertion(+)

切換到master分支:

$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits)

Git還會自動提示我們當前master分支比遠程的master分支要超前1個提交。

master分支上把readme.txt文件的最后一行改為:

goback master....

提交:

$ git add readme.txt $ git commit -m "goback master first modify" [master 0b56936] goback master first modify 1 file changed, 1 insertion(+)

現在,master分支和feature1分支各自都分別有新的提交,變成了這樣:

這種情況下,Git無法執行“快速合並”,只能試圖把各自的修改合並起來,但這種合並就可能會有沖突,我們試試看:

$ git merge feature1 Auto-merging readme.txt CONFLICT (content): Merge conflict in readme.txt Automatic merge failed; fix conflicts and then commit the result.

果然沖突了!Git告訴我們,readme.txt文件存在沖突,必須手動解決沖突后再提交。git status也可以告訴我們沖突的文件:

$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) You have unmerged paths. (fix conflicts and run "git commit") Unmerged paths: (use "git add <file>..." to mark resolution) both modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a")

我們可以直接查看readme.txt的內容:

test git modify second study git three add four add modify five add modify six add modify seven add modify eight add modify ... create new branch dev.. <<<<<<< HEAD goback master.... ======= create new branch feature1.. >>>>>>> feature1

Git用<<<<<<<=======>>>>>>>標記出不同分支的內容,我們修改如下后保存:

test git modify second
study git
three add
four add modify
five add modify
six add modify
seven add modify
eight add modify ...
create new branch dev..
create new branch feature1..
goback master....

再提交:

$ git add readme.txt $ git commit -m "fixed conflicts" [master 0f3d64a] fixed conflicts

現在,master分支和feature1分支變成了下圖所示:

用帶參數的git log也可以看到分支的合並情況:

$ git log --graph --pretty=oneline --abbrev-commit * 0f3d64a fixed conflicts |\ | * b4309b0 create new branch feature1 first modify * | 0b56936 goback master first modify |/
* 45ae9a9 create new branch.... * 90bc1f7 test name * c1bdf43 test commit * dd34c9a no add but commit,because use other parameter * 4ed30d1 eight modify dify * b45ca96 eight modify * 9332d40 seven modify * 72c6f9b six modify * f64b5a0 five modify * de8fd65 four modify * 83a4b1e three modify * 01c05cf two modify * 1acafa7 first modify * 09c1bba first git

最后,刪除feature1分支:

$ git branch -d feature1 Deleted branch feature1 (was b4309b0).

小結

當Git無法自動合並分支時,就必須首先解決沖突。解決沖突后,再提交,合並完成。

git log --graph命令可以看到分支合並圖。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM