修改commit歷史的前提
修改歷史的提交是可能有風險的,是否有風險取決於commit是否已經推送遠程分支,未推送,無風險,如果已推送,就千萬不要修改commit了。
修改commit歷史,不是在原有commit結點上修改,而是用一個新的結點替換原來結點,所以,修改后commit id是不樣的。
所以修改commit歷史的前提是,提交未推送遠程倉庫!提交未推送遠程倉庫!提交未推送遠程倉庫!,重要的事情說三遍。
修改最近的一次提交
修改最近的一次提交非常簡單,通過git commit --amend
,該命令可以讓我們修改提交的commit信息,也修改提交的內容。
修改提交的commit信息,可以直接運行該命令,然后在彈出的編輯框中修改提交信息保存即可。
修改提交的內容,可以先修改好內容,然后git add
暫存區,再使用git commit --amend
,填寫commit信息保存即可。
修改更早的提交或修改多個提交
修改更早的提交或修改多個提交就需要用到git rebase -i parentCommitID
,其機理是通過重新衍合parentCommitID之后的全部提交,所以該操作會改變parentCommitID結點之后所有提交的commit id。
通過rebase -i
我們可以交互式的運行rebase,以達到修改更早的提交或修改多個提交。
運行這個命令會彈出一個文本編輯器,其中包含了提交列表和一些簡單說明,形如:
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
你會發現提交列表的順序與通過git log
查看的命令是相反的,而且在每條提交前面都有一個pick
,在說明中有提到,是選擇該次提交,即不做修改,如果需要修改某個提交,就將對應記錄(可是多個記錄)的pick
改為edit
。保存,關閉文本編輯器后,回到命令行,會停在第一個標記為edit
的提交前,eg:
$ git rebase -i HEAD~3
Stopped at 7482e0d... updated the gemspec to hopefully work better
You can amend the commit now, with
git commit --amend
Once you’re satisfied with your changes, run
git rebase --continue
根據提示,修改完成之后執行git commit --amend
修改提交,然后執行git rebase --continue
繼續rebase。
所以rebase -i
的流程如下:
- git rebase -i parentCommitID
- 在彈出的文本編輯器中,將要修改的commit的前方的pick改為edit,保存,關閉文本編輯器
- 在命令行處於等待狀態后,修改內容
- 執行
git commit --amend
修改提交 - 執行
git rebase --continue
繼續rebase - 完成