1. 程式人生 > >git--分支管理:建立、合併、衝突解決

git--分支管理:建立、合併、衝突解決

宣告:文章原稿來源於恩師稀哥。
一、概念
分支就是科幻電影裡面的平行宇宙,當你正在電腦前努力學習Git的時候,另一個你正在另一個平行宇宙裡努力學習SVN。
如果兩個平行宇宙互不干擾,那對現在的你也沒啥影響。不過,在某個時間點,兩個平行宇宙合併了,結果,你既學會了git又學會了SVN!
在這裡插入圖片描述
分支在實際中有什麼用呢?假設你準備開發一個新功能,但是需要兩週才能完成,第一週你寫了50%的程式碼,如果立刻提交,由於程式碼還沒寫完,不完整的程式碼庫會導致別人不能幹活了。如果等程式碼全部寫完再一次提交,又存在丟失每天進度的巨大風險。
現在有了分支,就不用怕了。你建立了一個屬於你自己的分支,別人看不到,還繼續在原來的分支上正常工作,而你在自己的分支上幹活,想提交就提交,直到開發完畢後,再一次性合併到原來的分支上,這樣,既安全,又不影響別人工作。
二、建立與合併分支
git把我們之前每次提交的版本串成一條時間線,這條時間線就是一個分支。截止到目前只有一條時間線,在git裡,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向當前的具體版本,而是指向分支,也就是master分支,在master分支中才是指向具體的版本,所以,HEAD指標是通過這種機制來指向到具體的版本的。
(1) 一開始的時候,master分支是一條線,git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點:
在這裡插入圖片描述


每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長。
(2)當我們建立新的分支,例如dev時,git新建了一個指標叫dev,指向master所指向版本,再把HEAD指標指向dev指標,就表示當前分支在dev上:
在這裡插入圖片描述
git建立一個分支很快,因為除了增加一個dev指標,改變HEAD的指向,工作區的檔案都沒有任何變化。
(3)不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次後,dev指標往前移動一步,而master指標不變:
(4)假如我們在dev上的工作完成了,就可以把dev合併到master上。git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:
在這裡插入圖片描述

git合併分支也很快,因為也是隻改指標,工作區內容並沒有改變。
(5)合併完分支後,甚至可以刪除dev分支。刪除dev分支就是把dev指標給刪掉,刪掉後,我們就剩下了一條master分支:
在這裡插入圖片描述
相關操作命令:

	檢視分支:git branch
	建立分支:git branch <name>
	切換分支:git checkout <name>
	建立+切換分支:git checkout -b <name>
	合併某分支到當前分支:git merge <name>
	刪除分支:git branch -d <name>

案例分析:
(1)執行如下命令可以檢視當前有幾個分支

# git branch
* master

(2)下面建立一個分支dev並切換換到其上面進行工作

# git branch dev
# git branch
  dev
* master

# git checkout dev
Switched to branch 'dev'

# git branch
* dev
  master

此時的指標指向關係:
在這裡插入圖片描述
(3)下面我們修改code.txt內容,在裡面新增一行,並進行提交。

# echo "+++++++++">>code.txt 
# cat code.txt 
first line
second line
+++++++++
#  git add code.txt 
# git commit -m "新專案"
[dev 6147876] 新專案
 1 file changed, 1 insertion(+)

此時的指標關係:
在這裡插入圖片描述
(4)dev分支的工作完成,我們就可以切換回master分支:

# git checkout master
Switched to branch 'master'

# git branch
  dev
* master

此時的指標關係:
在這裡插入圖片描述
檢視code.txt,發現並沒有新增的內容。

cat code.txt 
first line
second line

原因是那個提交是在dev分支上,而master分支此刻的提交點並沒有變。
(5)現在,我們把dev分支的工作合併到master分支上:

# git merge dev
Updating 1a3efe2..6147876
Fast-forward    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 code.txt | 1 +
 1 file changed, 1 insertion(+)
# cat code.txt 
first line
second line
+++++++++

git merge命令用於合併指定分支到當前分支。合併後,再檢視code.txt的內容,就可以看到,和dev分支的最新提交是完全一樣的。
在這裡插入圖片描述
注意到上面的Fast-forward資訊,Git告訴我們,這次合併是“快進模式”,也就是直接把master指向dev的當前提交,所以合併速度非常快。
(6)合併完成後,就可以放心地刪除dev分支了,刪除後,檢視branch,就只剩下master分支了

# git branch -d dev
Deleted branch dev (was 6147876).
# git branch
* master

在這裡插入圖片描述
三、解決衝突
其實分支並不是總能合併成功的,例如這種情況下
在這裡插入圖片描述
此時,如果進行合併就會報錯,因為dev分支是基於master的v3版本中的內容,但是此時的master已經發生更改,因此此時合併就會發生錯誤,我們來模擬一下這種情況
(1)在建立一個新分支dev

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

# git branch
* dev
  master

(2)修改code.txt的內容,並提交

# echo "dev submit">>code.txt 

# cat code.txt 
first line
second line
+++++++++
dev submit

# git add code.txt 
# git commit -m 'dev 提交'
[dev d98c34a] dev 提交
 1 file changed, 1 insertion(+)

(3)切換回master分支

# git checkout master
Switched to branch 'master'

# git branch
  dev
* master

(4)在master的code.txt新增一行內容並且提交

# echo "master submit">>code.txt 
# git add code.txt 
# git commit -m 'master 提交'
[master e71cc6c] master 提交
 1 file changed, 1 insertion(+)

現在,master分支和dev分支各自都分別有新的提交,指標指向關係如下圖
在這裡插入圖片描述
這種情況下,合併就非常有可能會有衝突
(5)執行合併命令嘗試將dev分支合併到master分支上來,看一下會有怎樣的結果

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

看提示可以知道,code.txt檔案存在衝突,必須手動解決衝突後再提交。
(6)git status也可以告訴我們衝突的檔案

# git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

	both modified:   code.txt

no changes added to commit (use "git add" and/or "git commit -a")

(7)檢視code.txt的內容

# cat code.txt 
first line
second line
+++++++++
<<<<<<< HEAD
master submit
=======
dev submit
>>>>>>> dev

(8)
git用<<<<<<<,=======,>>>>>>>標記出不同分支的內容,我們修改如下後儲存:

# cat code.txt 
first line
second line
+++++++++
master submit
dev submit

(9)再提交

# git add code.txt 
# git commit -m "解決衝突"
[master 8301237] 解決衝突

# git status
On branch master
nothing to commit, working directory clean

(10)現在,master分支和dev分支變成了如下圖所示

在這裡插入圖片描述
(11)用帶引數的git log也可以看到分支的合併情況:

# git log --graph --pretty=oneline
*   8301237bf1feaee081c454efa48d500de6e4259a 解決衝突
|\  
| * d98c34a05b14fc887a8dea01a9f5582717536011 dev 提交
* | e71cc6c39adc3233523625fb67dac90a128e54ca master 提交
|/  
* 61478764554a5330958bf145b6f0d6121e92f8b6 新專案
* 1a3efe201b6e7fc66aa34f4ae9333a9ce2d54bb6 v2 -newversion
* c4106273b0b87ac6f42042589663900af3617837 v1

(12)最後工作完成,可以刪除dev分支

# git branch -d dev
Deleted branch dev (was d98c34a).

------做運維之前很矯情的小年輕-----