Git知識總覽(四) git分支管理之rebase 以及 cherry-pick相關操作


上篇博客聊了《Git知識總覽(三) 分支的創建、刪除、切換、合並以及沖突解決》,本篇博客我們主要來看一下 rebase 變基相關的操作。rebase 操作和 merge 操作最終都可以達到合並代碼的效果,不過其對分支的影響不同。上篇博客中我們聊到了 merge操作。簡單的說merge操作就是將兩個commit進行合並,然后在這兩個分支合並的基礎上創建一個新的commit。而變基操作簡單的說是改變提交的父類,在改變父類時進行合並操作。合並就可能產生沖突,所以rebase時也會產生沖突,下方會介紹到。

聊完rebase,下方還聊如何進行cherry-pickcherry-pick的本質其實也是合並,只不過是可以將任意分支,任意提交合並到相關分支。當然只要是合並操作,都有可能產生沖突,下方會給出cherry-pick操作的基本使用以及如何解決cherry-pick時產生的沖突。

 

一、merge 與 rebase 的簡單對比

下方是我們做操作之前的分支狀態,共有 bugFix、side 、another 三個分支。現在我們要做的是分別使用 merge 和 rebase 將分支 side 中的內容合並到master分支。

  

 

首先我們先來看一下 merge 操作。上篇博客中已經詳細的聊了merge的相關操作,再次就不做過多的展示了,下方只做了簡單的展示。

  • 首先切換到master分支
  • 然后在master分支上執行 git merge side 操作,將side分支上的內容合並到master分支上。
  • 最后如果需要的話,在將side分支的指針指向master分支即可。

  

 

然后我們再看一下 rebase 下的相關操作。

  • 首先切換到 side 分支。
  • 然后在 side 分支上執行 git rebase master 操作,將其變基到master分支上。

  

 

 

二、rebase的基本操作

首先我們來看一下在git分支管理中如何使用rebase, 以及rebase的后會起什么作用。下方會根據一系列的示例來看一下rebase操作的實際效果。首先我們先來看一下做rebase操作之前的分支狀態,如下所示。目前除了master主分支外,還有其他三個分支,分別為bugfix01、bugfix02、bugfix03。

現在要做的事情是在 bugfix01 的分支上執行rebase操作,將其變基到master分支上。

  

 

下方是在 bugfix01分支上執行的 git rebase master 將bugfix01分支變基到master分支上,下方是變基后的分支狀態。從下方的分支中不難看出,之前在 master 分支后方的 bugfix01現在跑到了master分支的后方,並且 bigfix01 分支上的兩個提交(3cc582b、f47d2ac)不見了。取而代之的是基於master分支的兩個新的提交(d6d82d8、14bc685)。這兩個新的提交不但包含了3cc582b、f47d2ac這兩個舊的提交的內容,而且還包含了master分支當前指向的分支(b79aa11)提交上的內容。

  

 

上面的表達也許有點抽象,下面我們可以話一張圖來表示上述的關系。根據上面的分支關系,簡單的畫了一下上面的 rebase 操作所對應的關系圖。rebase 操作完后,下方畫紅框的分支就被廢棄掉了。然后bugfix01會指向rebase后的commit上。

  

接着上面的操作,可以切換到master分支,然后執行 git merge bugfix01 命令,將master分支快速移動到bugfix01分支上所指向的內容上。下方就是快速移動后的結果。經過這步后,就完成了一次rebase操作。從rebase操作的結果來看,其對 git 的分支進行了整理,換句話說,rebase操作可以將其他分支上的內容合並到主分支上,合並后之前的分支的指針的指向也會隨之變化,變化后之前的提交就會被拋棄掉。

  

 

變基是存在一定風險的,在 ProGit上有一句話:Do not rebase commits that exist outside your repository. 大概意思就是說:不要在你的倉庫在其他地方存在副本的情況下,對分支執行變基。也就是說,你從遠程Clone下來代碼,然后對之前的操作進行了rebase, 並且強推到遠端。如果別人也clone的相關倉庫,在其分支上做了相關操作。在push之前執行pull時,因為之前的分支被你rebase了,也就是有了新的提交,在pull時,就會進行merge操作。這樣一來,分支就會更加復雜。如果出現上述問題 就使用rebase 來解決問題,即使用 git pull --rebase 來執行。

這一塊具體的東西還是參考ProGit上的內容來的比較直觀,在此就不做過多贅述了。

 

三、rebase的沖突解決

為了看rebase沖突的解決方式,我們故意的制造了下方的沖突,然后去執行rebase操作。從下方的操作中不難看出,在rebase的過程中產生了沖突,需要我們去解決。解決沖突后將相關問題件進行commit, 然后使用 git rebase --continue 操作來繼續rebase。

因為rebase時會合並多個提交,在多個提交合並時會產生多個沖突,所有在一個沖突解決並提交后,進行git rebase --continue繼續合並接下來的點。繼續后仍然有可能產生沖突,產生沖突即解決沖突,直到rebase結束為止。

 

 

四、cherry-pick的基本操作

接下來我們來看一下git中比較實用的一個命令:cherry-pick。這個命令的名字是比較形象的,cherry-pick即“摘櫻桃”,使用該命令可以將任意的commit通過其commit號將其合並到你想要的分支上。接下來我們就來看一個例子。

下方就演示了cherry-pick命令的使用方法。在 master 分支上,執行 git cherry-pick <一些commit的哈希值> 然后將這些提交合並到master分支上。這些分支會根據cherry-pick的順序進行merge,每次merge都會形成一個新的提交。與rebase命令不同,雖然會產生一個新的提交,而之前的提交是不變的。具體如下所示: 

  

 

接下來我們來看一下具體在終端上cherry-pick的操作命令。下方是目前分支的狀態,並且處於master分支上。現在我們要做的事情是將 d98ff43  這個commit 拿到master上。

  

 

下方就是我們執行cherry-pick的命令,如下所示。下方執行cherry-pick時是非常順利的,沒有產生沖突。當提交進行合並時會產生沖突,就不是這個樣子了,稍后會演示到。

  

 

下方就是順利的cherry-pick后的樣子。

  

 

五、cherry-pick的沖突解決

在cherry-pick時遇到沖突是避免的,下方特地搞了一個cherry-pick沖突的例子。為了更進一步的了解沖突的解決方式,下方cherry-pick了多個提交,而且這多個提交在merge時都會有沖突。下方我們會對這些沖突進行解決。

  • 首先我們在master分支上通過 git cherry-pick <一系列提交的哈希值>來將 4f8e019、dbe9e8a、5c52520這三個提交摘到master分支上。
  • 然后我們會先看到在cherry-pick 4f8e019 這個提交時產生了沖突,報了一個Error:提升不能將cherry-pick命令應用於4f8e019。並且下方給了一系列的提示(解決此錯誤可以通過正確的方式解決沖突,然后通過git add 或者 git rm將更改的文件進行追蹤,最后可以使用 git commit進行提交)
  • 解決一個沖突並commit后,使用 git cherry-pick --continue可以進一步的進行下一個提交的cherry-pick。下方再次執行git cherry-pick --continue時,又出現了沖突,此刻我們還是按照上述的步驟對沖突進行解決,解決完畢后接着git cherry-pick --continue。直到所有的commit被合並完畢即可。具體操作步驟如下所示:

  

 

下方是上述操作的最終結果,cherry-pick了三個commit,沖突了三次,解決了三次。如下所示:

  

 

下篇博客會繼續聊Git的相關的內容。


免責聲明!

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



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