[git] git 分支( branch ) 的基本使用

分支( branches ) 是指在開發主線中分離出來,作進一步開發而不影響到原來主線。html

Git 存儲的不是一系列的更改集( changeset ),而是一系列快照。當你執行一次 commit 時, Git 存儲一個 commit 對象,它包含一個指針指向你當前須要提交的內容的快照。git

Git 中的 master 分支的功能,和其餘分支同樣。master 在 git 項目中常見到,是由於 git init 命令運行時默認建立一個分支,並命名爲 master。github

建立一個新的分支,就是建立一個新的指針,用來在快照間移動。Git 經過 HEAD 指針,指向當前工做的本地分支。shell

$ git branch testing

 

使用 git checkcout 命令,能夠切換分支。vim

$ git checkout testing

 

修改文件並 commit 代碼後,會移動分支的指針測試

$ vim test.rb
$ git commit -a -m 'update test.rb'

經過 checkout 能夠切換回去 master 分支。下面的命令作了兩件事,一是把 HEAD 指針指向了 master 分支,二是當前工做目錄的文件恢復到了 master 所指向的快照版本。也就是說 87ab2 提交的變更,在切換到 master 分支時被移除。網站

$ git checkout master

 

再作一些變動和 commit 。注意,此時歷史記錄開始出現分叉。spa

$ vim test.rb
$ git commit -a -m 'make other changes'

Git 中的分支,其實是一個簡單的包含 40 個字符的文件,這 40 個字符是一次提交所產生的 SHA-1 checksum。因此,在 Git 中建立和銷燬一個分支的成本很是低。這個和其餘大多數版本管理系統比起來,Git 無需拷貝整個項目的文件,是一個巨大的不一樣點。3d

 

基本的分支與合併指針

下面的例子是一個比較常見的場景,應用了分支與合併的功能。

  1. 在開發一個網站
  2. 建立一個分支 ( iss53 ),用於處理新的項目需求( user story )
  3. 在這個分支上,作了一些工做

這時,接收到另外一個緊急的問題,須要馬上修復( hotfix )

  4. 切換到生產環境分支

  5. 建立一個新的分支 ( hotfix ),用於修復線上問題

  6. 測試事後,把修復分支合併到主分支上,並推送到生產環境 

  7. 切換到原來的需求分支,繼續工做

最開始的狀態以下

經過 branch / checkout / commit 等操做,作到上面的第 5 步, 狀態以下

接下來,先合併 hotfix 分支,而後部署到線上環境。

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

上面的提示中,有 Fast-forward 字眼,代表 hotfix 分支指向的 c4 提交,是 master 分支指向的 c3 提交的祖先,所以,直接把 master 移動到 c4 便可。合併後效果關係以下

因爲 hotfix 已經合併到 master 分支,此時 master 和 hotfix 指向同一個地方,後續不在須要用到 hotfix 分支,因此能夠刪除。

$ git branch -d hotfix

下來了能夠切換到 iss53 分支繼續工做,繼續修改,而後提交。當修改完畢後,關係大體以下

$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)

 

接下來開始合併。

$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

這裏合併無了 Fast-forward 字眼,由於不是簡單的移動分支指針。Git 採用三路合併( three-way merge ) 方式進行合併,建立了一個 commit ( c6 ),用於包含合併後的結果。三路合併方式,是指經過兩個分支的最新提交( c4 和 c5 ),以及他們的共同祖先 c2,來進行分支合併。c6 是一個合併提交記錄,特別之處是有兩個祖先。 

此時,你已不在須要 iss53 分支,能夠刪除它.

$ git branch -d iss53

 

基本合併衝突處理

若是兩個分支修改同一個文件的同一個部分,例如同一行代碼,Git 不知道如何合併,認爲這是一個衝突。例如你在 iss53 和 hotfix 分支都修改了 index.html 文件的同一個部分,合併 iss53 到已包含 hotfix 的 master 分支時,效果以下

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

此時,自動合併暫停,須要手動合併。 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:      index.html

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

Git 在衝突的文件中添加標準的衝突解決標識。

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

這個代表,HEAD 版本的代碼是 ======= 以上部分,iss53 的版本是 ======= 如下部分。

開打 index.html 文件,修改爲本身想要的版本,並剔除 <<<<<<< ======= >>>>>>> 標識,而後用 git add 標識衝突已接近,而後git commit 提交解決衝突後的版本。

 

參考資料

3.1 Branches in a Nutshell, git-scm

3.2 Basic Branching and Merging, git-scm

相關文章
相關標籤/搜索