本文主要參考git
rebase在git中是一個很是有魅力的命令,使用得當會極大提升本身的工做效率;相反,若是亂用,會給團隊中其餘人帶來麻煩。它的做用簡要歸納爲:能夠對某一段線性提交歷史進行編輯、刪除、複製、粘貼;所以,合理使用rebase命令可使咱們的提交歷史乾淨、簡潔!shell
當咱們在本地倉庫中提交了屢次,在咱們把本地提交push到公共倉庫中以前,爲了讓提交記錄更簡潔明瞭,咱們但願把以下分支B、C、D三個提交記錄合併爲一個完整的提交,而後再push到公共倉庫。測試
如今咱們在測試分支上添加了四次提交,咱們的目標是把最後三個提交合併爲一個提交:spa
這裏咱們使用命令:日誌
git rebase -i [startpoint] [endpoint]
其中-i
的意思是--interactive
,即彈出交互式的界面讓用戶編輯完成合並操做,[startpoint]
[endpoint]
則指定了一個編輯區間,若是不指定[endpoint]
,則該區間的終點默認是當前分支HEAD
所指向的commit
(注:該區間指定的是一個前開後閉的區間)。
在查看到了log日誌後,咱們運行如下命令:code
git rebase -i 36224db
或:get
git rebase -i HEAD~3
而後咱們會看到以下界面:it
上面未被註釋的部分列出的是咱們本次rebase操做包含的全部提交,下面註釋部分是git爲咱們提供的命令說明。每個commit id 前面的pick
表示指令類型,git 爲咱們提供瞭如下幾個命令:ast
- 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的合併了:
當咱們項目中存在多個分支,有時候咱們須要將某一個分支中的一段提交同時應用到其餘分支中,就像下圖:
咱們但願將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
注:由於[startpoint]
[endpoint]
指定的是一個前開後閉的區間,爲了讓這個區間包含C提交,咱們將區間起始點向後退了一步。
運行完成後查看當前分支的日誌:
能夠看到,C~E部分的提交內容已經複製到了G的後面了,大功告成?NO!咱們看一下當前分支的狀態:
當前HEAD處於遊離狀態,實際上,此時全部分支的狀態應該是這樣:
因此,雖然此時HEAD所指向的內容正是咱們所須要的,可是master分支是沒有任何變化的,git
只是將C~E部分的提交內容複製一份粘貼到了master所指向的提交後面,咱們須要作的就是將master所指向的提交id設置爲當前HEAD所指向的提交id就能夠了,即:
git checkout master git reset --hard 0c72e64
此時咱們才大功告成!
問題:
git rebase -i head~2
error: 沒有父提交的狀況下不能 'squash'
您能夠用 'git rebase --edit-todo' 修正,而後執行 'git rebase --continue'。
或者您能夠用 'git rebase --abort' 終止變基。