上篇博客聊了《git分支管理之rebase 以及 cherry-pick相關操做》本篇博客咱們就以Learning Git中的關卡進行展開。下方列舉了LearningGit中的 merge、rebase、reset、revert、cherry-pick 以及交互式rebase相關關卡的操做以及對應的解析。後邊在聊交互式rebase操做是,不僅僅給出了LearningGit中的內容,並且給出了真正的Git分支在交互式rebase操做時的具體案例。html
learngitbranching的地址爲:https://learngitbranching.js.org/git
1、代碼合併shell
在下方示例中全部目標的初始化狀態是下方這樣的,而後咱們要按照目最終目標,使用相關的git命令來達到相關的目標。vim
一、git merge編輯器
下方就是咱們要達到的目標,下方是咱們達到下方目標所要作的事情:ide
首先須要作的就是建立一個新的分支bugFix, 並切換到該分支上,而後進行一次C2的提交。
而後再切回到master分支上,進行一次新的提交(C3)。
最後要作的就是在master分支上執行一次合併操做,將bugFix分支上的提交合併到master分支上,C4就是合併後的節點。
下方對應的就是咱們實現上述目標所對應的命令操做,具體以下所示:post
首先使用 git checkout -b bugFix, 新建並切換到bugFix分支上,而且使用 git commit 命令進行一次提交生成C2節點。
而後使用 git checkout master 命令切換到master分支上,而且使用 git commit 命令進行一次提交生成C3節點。
最後的話,就是在 master 分支上執行 git merge bugFix命令,將bugFix分支合併到master分支上,合併後會生成一個新的C4節點。具體以下所示:
二、git rebase spa
闖完git merge的關,咱們來看一下git rebase的關。下方就是咱們最終要實現的目標。實現下方目標和上面的merge操做差很少,只不過最後一步不是使用合併操做,而是在bugFix上執行變基操做,具體分析以下:3d
首先須要作的就是建立一個新的分支bugFix, 並切換到該分支上,而後進行一次C2的提交。
而後再切回到master分支上,進行一次新的提交(C3)。
而後在切換到 bugFix 分支上,執行變基操做,將bugFix的父節點變成master分支,以前的C2節點就被新的提交C2`所替代了。
下方是咱們的具體命令操做:指針
首先使用 git checkout -b bugFix, 新建並切換到bugFix分支上,而且使用 git commit 命令進行一次提交生成C2節點。
而後使用 git checkout master 命令切換到master分支上,而且使用 git commit 命令進行一次提交生成C3節點。
而後再使用 git checkout bugFix 命令切回到 bugFix 分支上。
最後在bugFix分支上執行 git rebase master 命令,經其父類變成master。執行變基後,C2會和C3節點的內容進行合併生成新的節點C2`,而bugFix分支的指針也會從C2節點移動到C2`上,移動後bugFix以前的分支就會被廢棄掉,取而代之的是從master延續下來的新分支。
2、分離HEAD
一、移動HEAD指針
HEAD指針是指向當前所在的操做分支,好比咱們如今是在master分支,那麼HEAD就指向master分支,而後master分支指向的是咱們的commit號。分離的 HEAD 就是讓其指向了某個具體的提交記錄而不是分支名。下方左邊的圖就是咱們要完成的目標,右邊是咱們分支的初始化狀態。
實現上述目標一行命令足矣,可使用 git checkout C3 命令就能夠將HEAD命令指向C3提交上。git checkout HEAD^ 命令能夠將HEAD指針向上移動一個距離,git checkout HEAD~3 則能夠將HEAD向上移動三個距離。具體操做以下所示:
二、在提交樹上移動分支
下方要完成的不僅僅是HEAD指針的移動,而是分支指針的移動,在Git上能夠移動你所建立分支的指向,使其指向任意提交過的分支上。下方就來看一下如何在git上移動分支指針,下方左邊是咱們要完成的目標,右邊是分支的初始化狀態。須要作的事情以下:
將 bugFix 分支移動到C0上。
而後將master分支移動到C6上。
最後將HEAD分支上移。
須要操做的命令以下所示:
首先使用 git branch -f bugFix C0 命令將bugFix指向C0節點。(C0表示的是相關提交的哈希值)。
而後使用 git branch -f master C6 命令將master分支指向C6節點。
最後使用 git checkout HEAD^ 命令將分離的HEAD指針進行上移。
三、撤銷操做
接下來咱們來看一下撤銷操做,一樣左邊是咱們要完成的目標,右邊是初始狀態。從下方的目標中咱們能夠看出 local 分支的撤銷操做是使用的 git reset 操做的, 由於是在本地來向上移動的,進行reset後是不能夠push到遠端的。而push分支使用的是revert操做,撤銷了C2的提交後,再C2的基礎上又生成了一個新的提交。reset 操做是不能夠被push到遠端的,而revert則能夠,稍後會進行實驗。下方會有具體的操做。
下方就是咱們爲了完成目標而又的具體的操做:
首先在 local 分支上執行 git reset HEAD^1 或者 git reset HEAD C1 操做來撤銷本地的C3操做。
而後咱們再經過 git checkout pushed操做切換到 pushed 分支上,而後執行 git revert HEAD^1 操做,撤銷C2的提交。
若是你reset某個提交,想在將分支號移動到以前的提交上,可使用上面的 git branch -f 操做,將相應的分支移到相應的提交上。下方是將 local 分支又移動回了C3, 以下所示。
接下來我來看一下對 reset 後的分支進行push, 以及對 revert 分支後進行push。
首先在local分支上執行reset操做,而後進行push會提示本地倉庫和遠程倉庫產生了分歧,先git pull 或者 git pull --rebase。
而在pushed分支上的revert操做就不會有這樣的提示,由於revert是在原來的分支下方產生了一個新的提交,和正常提交同樣對待,因此是能夠push的。
下方咱們再作個嘗試,在一個分支上進行了reset , 而後在reset後的分支上作了一些提交。最後咱們將這些提交進行push,而後看一下具體的效果。
首先咱們對clone到本地的local分支進行了reset操做,操做後在新的分支上進行兩次commit。
而後咱們進行push , 會提示先pull或者 pull --rebase , 而後在進行push.
下方先執行了 git pull 操做,執行pull操做後,就是將 o/local 分支和 local分支進行合併,合併後就能夠進行push了。這樣一來,咱們以前reset操做就不起什麼做用了。由於 pull 操做後進行了merge, 就等效於在C3上直接進行commit。
而後咱們進行回退,又試了一下 git pull --rebase 操做,其實該操做就是將merge操做改爲了變基操做。將咱們後來的C4, C5兩個提交變基到C3上,從效果上看,就和沒有執行reset操做同樣。具體以下所示:
3、cherry-pick和交互式rebase
之因此將這兩個放在一塊,是由於使用二者均可以達到相同的目標,只是操做不一樣。下方會分別介紹。
1. cherry-pick
下方咱們來看一下cherry-pick這一關,下方咱們須要將 bugFix 分支上的 C3 、side 分支上的 C4 以及another分支上的C7經過cherry-pick的形式拿到 master分支上。
下方主要仍是使用了cherry-pick來達到咱們的目標的,主要仍是一個命令的使用 , 在 master 分支上執行 git cherry-pick C3 C4 C7, 能夠將C3 C4 C7這三個提交摘到master分支上了。具體以下所示:
二、交互式rebase
解析咱們來使用交互式rebase來作節點的遷移,固然下方的操做也是可使用cherry-pick來完成的。左邊是咱們要完成的目標,右邊則是初始化狀態。咱們須要將C2 C3 C4 C5的提交順序轉換成C3, C5, C4的順序。
下方就是咱們交互式rebase操做的具體步驟,本質上就一個命令 git rebase -i HEAD~4, 而後操做相關的節點便可。
三、交互式rebase實踐
接下來咱們來看一下在真正的git分支上是如何使用交互式rebase操做的。下方是作交互式rebase操做以前的分支關係。目前所在的分支是bugFix, 其中有4個提交。
如今要作的是在bugFix上進行交互式rebase, 在終端中輸入 git rebase -i master, 目的是將 bugFix 分支上的提交經過交互式rebase的方式將其變基到master分支上。下方是輸入git rebase -i maste命令後所出現的界面,咱們能夠經過vim編輯器編輯將要執行的變基操做。下方是對應的幾種交互式命令
pick 應用相關提交。
reword 修改commit信息。
edit 對提交進行編輯,而後使用 git commit -amend進行提交。
squash 是把多個提交合併成一個提交
fixup 與squash差很少,不過會拋棄掉本次提交的log信息
exec 執行shell命令
drop 刪除提交
下方咱們對相關操做執行的交互式的操做:
首先使用 reword 來操做下方截圖中的第一條操做,用來修改message。
而後交換了第二行和第三行的pick的位置
而後對第四行的提交執行edit命令對其進行修改
而後刪除 編號爲04的提交
點擊回車鍵的話會彈出下方的vim編輯器來讓你修改 f53560c 這個操做的commit message,修改完畢後進行保存便可。
下方是在rebase合併時產生了衝突,咱們須要對衝突進行解決。解決完畢後,執行 git add 將衝突文件進行存儲,而且執行git rebase --continue 來繼續咱們的rebase操做。
通過一系列解決衝突的操做,最終咱們的rebase操做是成功的,會提示下方的 Successfully。
交互式rebase操做成功後,接下來咱們來看一下當前分支的狀況,,從結果中咱們不難看出:
bugFix 分支上的提交已經變基到了master分支上。
「change aa.text 04」的提交已經被移除了。
「change aa.text 01」 和 「change aa.text 02」 的提交順序進行了交換。
而且 "create aa.text" 的log變成了 "create aa.text reword"
四、交互式rebase的squash操做
接下來咱們來看一下squash的操做,下方咱們會在當前所在分支和上次提交上執行squash操做,其對應的命令的爲:git rebase -i HEAD~1,以下所示:
咱們對該操做執行squash命令,以下所示,編輯完進行保存便可。
保存後會出現下方的操做,目的是用來編輯兩次提交合並後的commit message 的。
編輯完保存便可,下方就是咱們進行上述操做後所對應的相關信息。
五、交互式rebase的另外一個示例
接下來咱們來看一下另外一個交互式rebase的示例,完成下方的目標,咱們須要作下方几步:
首先咱們經過交互式rebase將caption變基到master分支上,在變基操做時交換 C2 和 C3的位置。
而後經過 git commit --amend 往 C2 上追加提交內容。
最後再經過 git rebase -i 操做將C2和C3進行交換。
下方就是對應的具體命令操做:
首先在caption分支上執行 git rebase -i master, 將caption分支經過交互式rebase的方式變基到master分支。
在交互式變基時,修改了C2和C3的提交順序。
而後在經過git commit -amend 操做往C2上追加了一些修改。
而後再經過git rebase -i master , 將C2和C3進行交換回來。
最後將master使用git rebase 操做進行快速移動到caption上。
今天博客就先到這兒吧,下篇博客繼續聊git相關的內容。