git修改和合并历史提交
git忠实记录自己提交的每一次修改,修改历史记录不是一个好习惯。不过在日常使用中,偶尔也有遇到需要修改过去提交记录的情况,比如,commit之后发现message少写了一些功能说明(如果想撤回整个commit修改,请自行搜索*git revert*哈),有时候甚至是在十几次提交之后才发现某次提交说明有误。又比如,因为某个功能比较复杂,作者想通过多次commit来记录修改以便方便回退,但是在推到项目仓库,发出合并请求的时候,意识到主仓库不需要记录太多commit时,就有了将请求合并的需求。
修改历史提交说明
git的rebase命令提供了对历史提交进行修改的功能。
git log
找到想要修改的commit的上一个commit的idgit rebase -i [ID]
进入交互模式,此时可以看到形如pick ed03fd1 test pick f5c2a41 test # Rebase fa0ab51..f5c2a41 onto fa0ab51 (2 command(s)) # # 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 # # 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
非注释部分即为刚那个ID之后的两次提交(知道为什么rebase命令后跟的是上一个commit了吧),最新的在最下面。根据注释部分的说明,将第一行的pick
改为e
,然后:wq
退出,此时HEAD会返回到该提交处,执行git commit --amend "修改之后的message"
,再执行git rebase --continue
即可将该提交的message修改并返回到最新状态。
合并历史提交
合并历史提交与上个操作基本相同。调出上步中的交互界面后,将想要合并的commit的pick
改为s
,然后:wq
退出,此时后进入下一个交互界面,形如
# This is a combination of 2 commits.
# The first commit's message is:
first commit
# This is the 2nd commit message:
second commit
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Mon May 30 21:23:57 2016 +0800
#
# rebase in progress; onto fa0ab51
# You are currently editing a commit during a rebase.
#
# Changes to be committed:
# new file: fist_file
# new file: second_file
#
这里显示了这两次commit的message,此时随你喜欢将两次message保留也好,自己重新写也好。同样:wq
保存,即可将两次提交合并。
因为最新提交在最下面,所以,该pick
为s
的提交会与上一提交合并,如果是连续修改pick
,则可以将多个提交合并起来。所以如果遇到这样的报错
Cannot 'squash' without a previous commit
原因就是修改了第一行的pick
,因为之上是没有commit的,所以会报错。一旦遇到这个问题,执行
rm -fr "[REPO PATH]/.git/rebase-merge"
后重新操作即可。
因此,执行git rebase
命令进行提交合并的时候,指定的commit的ID必须是本次合并相关的commit的上个commit,而不仅仅是被合并commit的上个commit。