在平常開發中,咱們的Git提交原則常常是小功能屢次提交,可是有時須要在完成功能以後將多個連續的提交合併成一個,或者進行分支合併時,只保留一個提交,以保證分支簡介,這時就須要進行squash操做,兩種分別稱爲 Rebase Squash 和 Merge Squash。這篇tip主要記錄如何處理這兩種操做以及之間的區別,git
<!--more-->shell
用來將多個連續的提交合併爲一個,如下面的提交記錄爲例,master
是主分支,分支 featureY
提交了一系列的修改:編輯器
$ git lg * 392dc11 - (HEAD -> featureY) Y5 (5 minutes ago) <qiwihui> * 740e7d2 - Y4 (5 minutes ago) <qiwihui> * b54cd87 - Y3 (5 minutes ago) <qiwihui> * fb3a5cf - Y2 (6 minutes ago) <qiwihui> * 61b5ff9 - Y1 (6 minutes ago) <qiwihui> * 220e45c - (master) feature X (7 minutes ago) <qiwihui>
其中,lg
是以下命令:post
[alias] lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --
這裏咱們須要合併 featureY
功能分支上的 Y1
到 Y5
這五個提交爲一個。git提供了以下命令:ui
git rebase --interactive HEAD~[N] # 或者 git rebase -i HEAD~[N]
其中 [N]
表示須要合併的數量,從最近一個提交開始數,這裏爲5
。在命令行輸入 git rebase --interactive HEAD~5
進入編輯器進行選擇。
注意,這裏的提交順序是 反 的,從最先的 Y1
開始:spa
pick 61b5ff9 Y1 pick fb3a5cf Y2 pick b54cd87 Y3 pick 740e7d2 Y4 pick 392dc11 Y5
對應須要合併的提交,將pick
改爲squash
(或者簡化爲s
),修改以後爲:命令行
pick 61b5ff9 Y1 s fb3a5cf Y2 s b54cd87 Y3 s 740e7d2 Y4 s 392dc11 Y5
保存並關閉編輯器,這是編輯器會自動跳出並須要你提交一個新的提交:code
# This is a combination of 5 commits. # This is the 1st commit message: Y1 # This is the commit message #2: Y2 # This is the commit message #3: Y3 # This is the commit message #4: Y4 # This is the commit message #5: Y5 # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Thu May 9 13:45:03 2019 +0800 # # interactive rebase in progress; onto 220e45c # Last commands done (5 commands done): # squash 740e7d2 Y4 # squash 392dc11 Y5 # No commands remaining. # You are currently rebasing branch 'featureY' on '220e45c'. # # Changes to be committed: # new file: featY #
能夠看到,Git提供了詳細的信息指導提交,只須要修改爲你須要的信息便可,好比 featureY
,而後保存。這時就完成了修改,修改以後的提交信息以下:orm
$ git lg * 1b07941 - (HEAD -> featureY) featureY (3 minutes ago) <qiwihui> * 220e45c - (master) feature X (36 minutes ago) <qiwihui>
用於在合併分支時,最後只在合併後的分支上保留一個提交。一樣以上面的代碼提交爲例子。blog
$ git lg * 392dc11 - (HEAD -> featureY) Y5 (5 minutes ago) <qiwihui> * 740e7d2 - Y4 (5 minutes ago) <qiwihui> * b54cd87 - Y3 (5 minutes ago) <qiwihui> * fb3a5cf - Y2 (6 minutes ago) <qiwihui> * 61b5ff9 - Y1 (6 minutes ago) <qiwihui> * 220e45c - (master) feature X (7 minutes ago) <qiwihui>
$ git checkout master $ git merge --squash featureY Updating 220e45c..392dc11 Fast-forward Squash commit -- not updating HEAD featY | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 featY
此時,分支featureY
保持不變,同時在master
上多了一個未被提交的更改:
$ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: featY
這些更改是分支featureY
中全部提交的合併,如今只須要提交這些更改就能夠了:
git commit -m "featureY"
從以上的擦坐過程能夠看出二者之間的差異:Rebase Squash會合並以前的提交,以前的記錄會消失,而Merge Squash只會在合併的分支上新生成提交,原來的那些提交熬還會保留。
若是須要合併的提交數量不少,數數容易出錯,可使用提交哈希來識別:
git rebase --interactive [commit-hash]
這個[commit-hash]
是須要合併的提交以前的一個提交:
$ git lg * 392dc11 - (HEAD -> featureY) Y5 (5 minutes ago) <qiwihui> * 740e7d2 - Y4 (5 minutes ago) <qiwihui> * b54cd87 - Y3 (5 minutes ago) <qiwihui> * fb3a5cf - Y2 (6 minutes ago) <qiwihui> * 61b5ff9 - Y1 (6 minutes ago) <qiwihui> * 220e45c - (master) feature X (7 minutes ago) <qiwihui>
這裏,須要使用 220e45c
而不是 61b5ff9
。