當我們想要修改以前的 commit,可以使用 rebase 指令來達成。這裡準備了簡單一個情境來說明
現在資料夾中有兩個檔案,a.txt和b.txt。且我們分別在修改了這兩個檔案後都 commit 了一次,包含初次的 commit,我們一共有三個 commit。
$ git log --oneline
27db2a2 (HEAD -> master) edit b.txt
e91d1f8 edit a.txt
55703db a.txt & b.txt
但我們不想要這麼多個 commit,想要把後面的兩次的修改改成同一次 commit
這時我們可以使用git rebase -i
這個指令來進入互動模式:
$ git rebase -i HEAD~2
我們想要修改最後的兩個 commit,所以在後面加上 HEAD~2。 這時會跳出編輯器讓你編輯你想要修改的內容:
pick e91d1f8 edit a.txt
pick 27db2a2 edit b.txt
# Rebase 55703db..27db2a2 onto 55703db (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
在編輯器的註解中,親切的附上了註解,這裡我們只想保留一個 commit,並把另一個合併進去。
因此我們選擇對後面的那一個 commit 使用squash
(或是簡寫成s
)。
pick e91d1f8 edit a.txt
squash 27db2a2 edit b.txt
# Rebase 55703db..27db2a2 onto 55703db (2 commands)
# ...
將pick
改成squash
後存檔離開,我們會發現馬上又跳出了一次編輯器:
# This is a combination of 2 commits.
# This is the 1st commit message:
edit a.txt
# This is the commit message #2:
edit b.txt
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Sat Dec 21 21:33:32 2019 +0900
#
# interactive rebase in progress; onto 55703db
# Last commands done (2 commands done):
# pick e91d1f8 edit a.txt
# squash 27db2a2 edit b.txt
# No commands remaining.
# You are currently rebasing branch 'master' on '55703db'.
#
# Changes to be committed:
#>--modified: a.txt
#>--modified: b.txt
這時是讓我們可以重新編輯一次 commit 訊息,於是我們將 commit 訊息修改為編輯了兩個檔案
# This is a combination of 2 commits.
# This is the 1st commit message:
edit a.txt & b.txt
# This is the commit message #2:
# edit b.txt
# Please enter the commit message for your changes. Lines starting
# ...
這樣就修改完成了,我們再看看變成甚麼樣子了:
$ git log --oneline
7e00372 (HEAD -> master) edit a.txt & b.txt
55703db a.txt & b.txt
commit 數從三個減少成兩個了!我們成功將這兩個 commit 合併成為了一個。 且從 commit 的 HASH 值可以看出,這是一個全新產生的 commit。
這時候可能還有另一個問題,如果我很不幸的其實已經將原本的 commit push 到 remote 了該怎麼辦呢? 這時候別無他法,我們只能使用 force push 的方式來覆蓋遠端的存檔了。
$ git push origin +master
但要注意!使用 force push 將可能影響到別人!
+
號與--force
的差異可以發現我在這裡的示範中使用了+master
的方式,如果只有 push 這一條 branch 時,與下面這樣是完全一樣的:
$ git push --force origin master
但當你不只 push 一條 branch 時,使用+
號讓你可以指定需要 force 的項目,例如:
$ git push origin master +develop
這個指令讓我們可以只針對 develop 使用 force push,而使用--force
將會使全部 push 的 branch 都使用 force push。