【git命令】git-rebase
修改歷史提交記錄
作用簡要概括為:可以對某一段線性提交歷史進行編輯、刪除、複製、貼上;因此,合理使用rebase命令可以使我們的提交歷史乾淨、簡潔!
前提:不要通過rebase對任何已經提交到公共倉庫中的commit進行修。
1.合併多個commit為一個完整commit
我們在本地倉庫中提交了多次,在我們把本地提交push到公共倉庫中之前,為了讓提交記錄更簡潔明瞭,我們希望把如下分支B、C、D三個提交記錄合併為一個完整的提交,然後再push到公共倉庫。
現在我們在測試分支上添加了四次提交,我們的目標是把最後三個提交合併為一個提交:
這裡我們使用命令:
git rebase -i [startpoint] [endpoint]
區間指定的是一個前開後閉的區間
其中-i
的意思是--interactive
,即彈出互動式的介面讓使用者編輯完成合並操作,[startpoint]
[endpoint]
則指定了一個編輯區間,如果不指定[endpoint]
,則該區間的終點預設是當前分支HEAD所指向的commit(注:該區間指定的是一個前開後閉的區間)。
在檢視到了log日誌後,我們執行以下命令:
git rebase -i 53d6d02df
或
git rebase -i HEAD~3
然後我們會看到如下介面:
上面未被註釋的部分列出的是我們本次rebase操作包含的所有提交,下面註釋部分是git為我們提供的命令說明。每一個commit id 前面的pick表示指令型別,git 為我們提供了以下幾個命令:
pick:保留該commit(縮寫:p) reword:保留該commit,但我需要修改該commit的註釋(縮寫:r) edit:保留該commit, 但我要停下來修改該提交(不僅僅修改註釋)(縮寫:e) squash:將該commit和前一個commit合併(縮寫:s) fixup:將該commit和前一個commit合併,但我不要保留該提交的註釋資訊(縮寫:f) exec:執行shell命令(縮寫:x) drop:我要丟棄該commit(縮寫:d)
根據我們的需求,我們將commit內容編輯如下:
然後是註釋修改介面:
編輯完儲存即可完成commit的合併了:
#2. 將某一段commit貼上到另一個分支上
當我們專案中存在多個分支,有時候我們需要將某一個分支中的一段提交同時應用到其他分支中,就像下圖:
我們希望將develop分支中的C~E部分複製到master分支中,這時我們就可以通過rebase命令來實現(如果只是複製某一兩個提交到其他分支,建議使用更簡單的命令:git cherry-pick
)。
在實際模擬中,我們建立了master和develop兩個分支:
master分支:
develop分支:
我們使用命令的形式為:
git rebase [startpoint] [endpoint] --onto [branchName]
其中,[startpoint]
[endpoint]
仍然和上一個命令一樣指定了一個編輯區間(前開後閉),--onto
的意思是要將該指定的提交複製到哪個分支上。
所以,在找到C(90bc0045b)和E(5de0da9f2)的提交id後,我們執行以下命令:
git rebase 90bc0045b^ 5de0da9f2 --onto master
可以看到,C~E部分的提交內容已經複製到了G的後面了,大功告成?NO!我們看一下當前分支的狀態:
當前HEAD處於遊離狀態,實際上,此時所有分支的狀態應該是這樣:
所以,雖然此時HEAD所指向的內容正是我們所需要的,但是master分支是沒有任何變化的,git只是將C~E部分的提交內容複製一份貼上到了master所指向的提交後面,我們需要做的就是將master所指向的提交id設定為當前HEAD所指向的提交id就可以了,即:
git checkout master
git reset --hard 0c72e64
此時我們才大功告成!
3. rebas合併,解決衝突
分支合併
如果圖中此時network 和 origin 分支有衝突了
平時我們用merge, merge合併,手動解決衝突,merge後會產生一個新的commit-id
分支合併,解決衝突, merge後會產生一個新的commit-id
rebase 合併
命令:
git checkout mywork
git rebase origin
命令會把你的"mywork"分支裡的每個提交(commit)取消掉,並且把它們臨時 儲存為補丁(patch)(這些補丁放到".git/rebase"目錄中),然後把"mywork"分支更新 為最新的"origin"分支,最後把儲存的這些補丁應用到"mywork"分支上。
當'mywork'分支更新之後,它會指向這些新建立的提交(commit),而那些老的提交會被丟棄。 如果執行垃圾收集命令(pruning garbage collection), 這些被丟棄的提交就會刪除. (請檢視 git gc)
在rebase的過程中,也許會出現衝突(conflict). 在這種情況,Git會停止rebase並會讓你去解決 衝突;在解決完衝突後,用"git-add"命令去更新這些內容的索引(index), 然後,你無需執行 git-commit,只要執行:
git rebase --continue
這樣git會繼續應用(apply)餘下的補丁。
在任何時候,你可以用--abort引數來終止rebase的行動,並且"mywork" 分支會回到rebase開始前的狀態。
git rebase --abort
如果你想跳過此補丁,則執行 git