Git中的分支
具體請參考:https://git-scm.com/book/zh/v1/Git-%E5%88%86%E6%94%AF-%E4%BD%95%E8%B0%93%E5%88%86%E6%94%AF
1、分支的概念
Git 中的分支,其實本質上僅僅是個指向 commit 對象的可變指針。Git 會使用 master 作為分支的默認名字。在若幹次提交後,你其實已經有了一個指向最後一次提交對象的 master 分支,它在每次提交的時候都會自動向前移動。
如下圖所示,在你提交了三次後,Git 中的默認分支(主分支)移動到了第三個提交對象上。圖中綠色的方框代表一個提交對象,紫色的可以看做是每個提交對象的有關操作(下面內容並不涉及到,可以忽略),灰色的是目前的分支。
2、創建新分支
$ git branch branchName //創建的是本地分支,當該分支已經存在時會提示已經存在了
創建新分支時會在當前分支的代碼上復制一份放到新分支上。
這會在當前 commit 對象上新建一個分支指針,如下圖:
我們可以通過 HEAD 指針來知道當前工作在哪個分支上。在 Git 中,它是一個指向你正在工作中的本地分支的指針(可以將 HEAD 想象為當前分支的別名。)。
運行 git branch
命令,僅僅是建立了一個新的分支,但不會自動切換到這個分支中去。如上例中我們仍然是在 master 分支上工作,如果繼續提交也將會只提交在 master 分支上。
2.1、創建並切換到新分支上(git checkout -b branchName)
要切換到其他分支,可以執行 git checkout
命令。
$ git checkout testing //切換到 testing 分支上 $ git checkout -b testing //新建testing分支並切換到該分支上,相當於同時執行了 git branch testing 和 git checkout testing
這樣 HEAD 就指向了 testing 分支
2.2、在不同分支上工作的原理
如果我們繼續在 testing 分支上工作時,比如新提交了一次,結果如下圖所示:
每次提交後 HEAD 隨著分支一起向前移動,現在 testing 分支向前移動了一格,而 master 分支仍然指向原先 git checkout
時所在的 commit 對象。
切換回 master 分支,git checkout master ,結果是如下圖的:
這條命令做了兩件事。它把 HEAD 指針移回到 master 分支,並把工作目錄中的文件換成了 master 分支所指向的快照內容(你的工作目錄上的文件將會自動變成在 master 分支上最新的提交版本一樣)。也就是說,現在開始所做的改動,將始於本項目中一個較老的版本。它的主要作用是將 testing 分支裏作出的修改暫時取消,這樣你就可以向另一個方向進行開發。
如果我們在 master 分支上工作,比如在 master 分支上提交了一次之後,我們的項目提交歷史產生了分叉,因為剛才我們創建了一個分支,轉換到其中進行了一些工作,然後又回到原來的主分支進行了另外一些工作。這些改變分別孤立在不同的分支裏:我們可以在不同分支裏反復切換,並在時機成熟時把它們合並到一起。如下圖:
在Git中創建和銷毀分支,在分支上切換等速度非常快,Git 鼓勵開發者頻繁使用分支
3、合並分支
3.1、需要創建新分支的情景
假設我們正在項目的本地 master 分支上工作(一般本地master分支也關聯遠程master分支),並且已經提交了幾次更新
但是項目出現了點問題,為了解決該問題,新建了一個新分支並取名為 iss53,希望在該分支上解決問題過後再合並到master分支上。
$ git checkout -b iss53
接著你開始嘗試修復問題,在提交了若幹次更新後,iss53
分支的指針也會隨著向前推進,因為它就是當前分支
這時項目上出現一個緊急 bug 必須修改,這時我們正在 iss53分支上工作,我們並不需要把目前的工作 push 到遠程倉庫,唯一需要的僅僅是切換回 master
分支去修改 bug 然後再提交到遠程倉庫的master分支上。
(不過在切換分支之前,我們必須先把目前所在的分支的修改提交 commit ,否則會報錯,切換分支的時最好保持一個清潔的工作區域)
此時工作目錄中的內容和你在解決問題 #53 之前一模一樣,你可以集中精力進行緊急修補。這一點值得牢記:Git 會把工作目錄的內容恢復為檢出某分支時它所指向的那個提交對象的快照。它會自動添加、刪除和修改文件以確保目錄的內容和你當時提交時完全一樣。
接下來我們進行修補bug,我們一般會在 master 分支上新建一個分支來修改 bug ,而不會直接在 master 分支上進行修改。比如創建了一個用來修補 bug 的 hotfix 分支,並在該分支上進行了一系列修補工作:
$ git checkout -b hotfix
3.2、合並分支(git merge 目標分支)
當我們確保在hotfix 上的分支修補是成功的後就可以回到 master
分支將它給合並起來,然後發布到遠程倉庫上。用 git merge
命令來進行合並(git merge
命令用於合並指定分支到當前所處的分支)
$ git checkout master
$ git merge hotfix
(請註意,合並時將可能出現“Fast forward”的提示。由於當前 master
分支所在的提交對象是要並入的 hotfix
分支的直接上遊,Git 只需把 master
分支指針直接右移。換句話說,如果順著一個分支走下去可以到達另一個分支的話,那麽 Git 在合並兩者時,只會簡單地把指針右移,因為這種單線的歷史分支不存在任何需要解決的分歧,所以這種合並過程可以稱為快進(Fast forward)。)
合並之後最新的修改都已經在 master 分支上了,我們就可以將 master 分支push 到遠程倉庫上。
3.3、刪除分支(git branch -d 分支名)
在改完 bug 以後,你想要繼續回去修改 iss53 的問題。由於當前 hotfix
分支和 master
都指向相同的提交對象,所以 hotfix
已經完成了歷史使命,可以刪掉了。使用 git branch
的 -d
選項執行刪除操作
$ git branch -d hotfix //刪除 hotfix 分支 $ git checkout iss53 //回到 iss53 分支繼續工作
註意:之前 hotfix
分支的修改內容尚未包含到 iss53
中來。如果需要納入此次修補,可以切換到 iss53 分支用 git merge master
把 master 分支合並到 iss53
;或者等 iss53
完成之後,再將 iss53
分支中的更新並入 master 也行
。
3.4、強制刪除未被合並的分支(git branch -D 分支名)
如果某一分支暫未被合並簡單地用 git branch -d
刪除該分支會提示錯誤,因為那樣做會丟失數據。這時如果我們仍然想刪除該分支的話可以使用強制刪除命令,比如在 hotfix 分支未被合並到 master 分支前將其刪除:
$ git branch -D hotfix
Git中的分支