使用git rebase合並多次commit
1. 背景
一個repo通常是由一個team中的多個人共同維護,如果需要增加新feature,那么就是一個feature分支了。由於開發中各種修改,本feature分支多次commit。最后提交master后,會看到亂七八糟的所有增量修改歷史。其實對別人來說,我們的改動應該就是增加或者刪除,給別人看開發過程的增量反而太亂。於是我們可以將feature分支的提交合並后然后再merge到主干這樣看起來就清爽多了。
記得知乎上有個帖子提問為啥vue的作者尤大大在開發vue的時候,提交歷史能做到如此清爽。Git commits歷史是如何做到如此清爽的? - 知乎
2. rebase簡介
rebase的作用簡要概括為:可以對某一段線性提交歷史進行編輯、刪除、復制、粘貼;因此,合理使用rebase命令可以使我們的提交歷史干凈、簡潔!
但是需要注意的是:
不要通過rebase對任何已經提交到公共倉庫中的commit進行修改(你自己一個人玩的分支除外)
3. 反面例子
新建一個repo rebase-test
;新建開發分支dev
;在開發分支是commit
了三次然后merge
到master
分支;然后git log
或者git log --oneline
;可以發現dev
分支上的每次commit
都體現到了master
上
fb28c8d (HEAD -> master, origin/master, origin/dev, origin/HEAD, dev) fix: 第三次提交 47971f6 fix: 第二次提交 d2cf1f9 fix: 第一次提交 26bac61 Initial commit
如果用
git log
可以按s
向下翻log
git log --oneline
可以一行展現
4. 具體操作
當我們在本地倉庫中提交了多次,在我們把本地提交push到公共倉庫中之前,為了讓提交記錄更簡潔明了,我們希望把如下分支B、C、D三個提交記錄合並為一個完整的提交,然后再push到公共倉庫。
這里我們使用命令:
git rebase -i [startpoint] [endpoint]
其中-i
的意思是--interactive
,即彈出交互式的界面讓用戶編輯完成合並操作,[startpoint] [endpoint]
則指定了一個編輯區間,如果不指定[endpoint]
,則該區間的終點默認是當前分支HEAD所指向的commit(注:該區間指定的是一個前開后閉的區間)。 在查看到了log日志后,我們運行以下命令:
git rebase -i 36224db
或者
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),只保留前一個commit信息。
exec:執行shell命令(縮寫:x)
drop:我要丟棄該commit(縮寫:d)
根據我們的需求,我們將commit內容編輯如下:
pick d2cf1f9 fix: 第一次提交
s 47971f6 fix: 第二次提交
s fb28c8d fix: 第三次提交
上面的意思就是把第二次、第三次提交都合並到第一次提交上
然后wq
保存退出后是注釋修改界面:
可以再瀏覽態 按下兩個dd可以刪除一行
編輯完保存即可完成commit的合並了:
最后查看log
可以發下提交合並了