咱們正在開發某個項目,爲了實現某個項目,咱們建立了分支task_113
,正在這個分支上開展工做。這個時候收到反饋說有個很嚴重的bug須要當即處理。這個時候,你應該當即切換到線上分支,爲這個bug創建新的分支issue_005
,並在這個分支上修復它。在測試經過後,切換到線上分支來合併issue_005
,最後將改動推到線上。而後切換回task_113
上繼續作新的需求。html
在沒開始作任務前,咱們倉庫的結構如上。如今咱們開始建立task_113分支:git
$ git checkout -b task_113
Switched to a new branch 'task_113'
複製代碼
這個時候咱們的git倉庫結構以下: github
這個時候咱們在當前分支上作了些工做,而且提交到了版本庫後,咱們的git結構以下: bash
這個時候咱們收到反饋的bug後,咱們當即切到master分支上,從master分支建立新的issue_005
分支開始解決線上的bug:測試
在切換到master以前,須要確認全部修改已經提交到版本庫中。ui
# 切換到master分支
git checkout master
Switched to branch 'master'
# 創建issue_005分支處理bug
git checkout -b issue_005
Switched to a new branch 'issue_005'
複製代碼
下面的圖是咱們如今git倉庫的狀態: spa
當issue_005分支上的修改測試完成後,咱們須要到master上將其合併。git checkout master
Switched to branch 'master'
git merge issue_005
Updating 04132ad..86e4899
Fast-forward
about.html | 1 +
1 file changed, 1 insertion(+)
複製代碼
Fast-forward: 表示的是在合併兩個分支的時候,若是順着一個分支走下去可以到達另外一個分支,那麼Git在合併二者的時候,只會簡單的將指針向前推動(指針右移),由於這種狀況沒有須要解決的分歧,這就叫作快進。3d
這個緊急問題處理完成後,咱們就能夠將issue_005這個分支刪除,由於咱們再也用不上它了。刪除完成後,咱們繼續回到task_113分支上繼續咱們的工做:指針
git branch -d issue_005
Deleted branch issue_005 (was 86e4899).
git checkout task_113
Switched to branch 'task_113'
git commit -a -v -m 'update index.html[task 113]'
[task_113 76e0e88] update index.html[task 113]
1 file changed, 1 insertion(+)
複製代碼
這個時候咱們再來看看咱們的倉庫結構: code
task_113的需求咱們已經完成了,而且測試經過,這個時候咱們應該開始將它合併到master上準本發佈到線上環境了。
git checkout master
Switched to branch 'master'
git merge task_113
Merge made by the 'recursive' strategy.
index.html | 2 ++
1 file changed, 2 insertions(+)
複製代碼
此次的合併並無像上次合併那樣,出現Fast-forward
。由於master分支所在提交併非task_113分支所提交的直接祖先,在這種狀況下,Git會使用兩個分支末端所指的快照(c4和c5)以及這兩個分支的共同祖先c2來一個簡單的三方合併。合併事後的倉庫結構爲:
這個時候咱們再把task_113分支刪除了就行了。咱們再看看git log --graph
的結果:
從上圖能夠看出,和咱們畫的結構圖徹底一致,接下來咱們再介紹下另一種方法變基
而變基則是提取出C4中引入的補丁和修改,在C3的基礎上應用一次。可使用rebase命令將提交的某一分支上的全部修改都移至另外一分支上。
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
複製代碼
這個時候咱們回到master上,進行一次快進合併:
git merge work
Updating 3462092..ece0ba5
Fast-forward
work.html | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 work.html
複製代碼
合併事後,咱們的倉庫結構爲:
仍是用git log --graph來看看最後的結構:
其實變基和合並同樣,最終都生成了一次新的提交,可是使用變基咱們讓提交歷史變得更加簡介,你能夠看到通過變基的分支的歷史記錄中,儘管開發工做是並行的,可是它們看起來就好像是穿行同樣,提交歷史是一條直線沒有分叉。在簡單的項目中,可能有點分叉也沒什麼,可是在一個多人維護的大型項目中,分叉多了項目的維護工做就會變得愈來愈複雜。
通常狀況下咱們用變基也就是爲了確保向遠程分支推送時可以保持提交歷史的簡潔:當咱們在github上修復別人項目的bug時,咱們首先在本身的分支裏開發,當開發完成後,你須要將你的代碼變基到origin/master上,而後再向主項目提交修改。這樣的話,該項目的維護者就再也不須要進行整合工做,而是快速合併便可。
使用變基的時候必定要記住一條規則:不要對在你的倉庫外有副本的分支執行變基。 變基操做本質上是丟棄一些現有的提交,而後相應的建一些內容同樣但實際不一樣的提交。若是你將提交推送到遠程倉庫上,而其餘人也從該倉庫拉取提交併基於你的分支建立了新的分支作後續工做,這個時候你用git rebase命令從新整理了提交再此推送,其餘人不得再也不次將它們手頭的工做與你的提交進行整合,若是他們還要拉去並整合他們修改過的提交,整個開發工做就會變得異常的混亂。想一想去年美國由於同事頻繁使用git push -f
推送到遠程分支而被同事槍擊的新聞吧,這樣你就能記住這條規則了。