修改最后一次提交

有的时候你可能会想修改上一次提交的信息,或者添加删除某些忘记的文件,那么在git add(若有文件变更)将待更改的文件加入后可以简单的执行:git commit --amend
这时会进入上次 commit 的文本编辑器,包含你上次提交的信息供你修改。你只需要修改为你想要的信息然后保存即可,保存退出后,在 log 中可以发现最近一次提交的信息已经被成功替换,并且 git hash 也已经改变(变基操作)。
若前一次的 commit 已经 push 到远程仓库,我们怎么修改远程仓库上次的 commit 呢?只需在上一步基础上执行:git push --force,该操作会将本地的提交覆盖远程仓库上一次的 commit。
由于这是变基操作,会覆盖历史,确保本地操作后的结果是自己想要的。

rebase 黄金法则:never use it on public branches. 不要在公共的branch上使用

Example:

git log中存在一个 commit ,此时 git 仓库有 file_1.txt 文件,并且有新建的 file_2.txt(假设是我们在上次 commit 中忘记添加的文件)

https://i.loli.net/2019/04/29/5cc6fc5163289.jpg

这时,我们执行 git commit --amend 进入文本编辑器,将信息更改为如下内容并保存退出:

https://i.loli.net/2019/04/29/5cc6fc5398ed4.jpg

再次执行 git log 发现 git hash 与 commit 都已经发生改变

https://i.loli.net/2019/04/29/5cc6fc55a2f66.jpg

修改多个提交信息

如果我们想修改不止前一次的提交,那么可以通过变基的操作修改一系列的提交:
命令:git rebase -i进行交互式变基,后面可以接HEAD~XX代表指定修改前X次提交(如 HEAD~3)
也可以从git log中直接复制想要修改到哪次的 HASH 值。接下来同样会进入文本编辑交互界面,根据提示信息修改相应的 action 后保存即可(后面提供 🌰)。
一般 action 有如下:

# Commands:
#  p, pick = use commit(默认 option)
#  r, reword = use commit, but edit the commit message(即修改 commit 信息)
#  e, edit = use commit, but stop for amending(修改 commit 信息,并在每条 commit 信息都会停下来,此时可以修改文件再 commit)
#  s, squash = use commit, but meld into previous commit(合并前一次提交组成新的提交)
#  f, fixup = like "squash", but discard this commit's log message(合并 commit,不组成新的提交)
#  x, exec = run command (the rest of the line) using shell(执行 shell 命令)
#  d, drop = remove commit(将此条 commit 删除)

需要注意的是在交互列表内的 commit 信息与 git log 中的信息是相反的,因为 git 会重演提交信息,所以旧的 log 会排在前面。

Example:

git log

https://i.loli.net/2019/04/29/5cc6fc58158e2.jpg

这里我们想要拆分第一条 commit,合并第二,三条 commit
于是我们执行 git rebase -i HEAD~3 进入交互界面对前三条 commit 进行修改(注意是倒序)
第一条 action 改为了 reword,因为后面的 fixup 会来合并,这时我们需要修改第一条的 commit (合并信息)
第二条 action 改为了 fixup,它会将改动自动合并到前一个 commit
第三条 action 改为了 edit,这时 rebase 会停下来等待修改完毕并执行 git rebase --continue 来完成,为了将这个 commit Add file_5.txt and file_6.txt 拆为两条信息,我们需要修改本地的文件并重新进行 commit。
现在我们保存并退出编辑器,继续接下来的操作
(下图也印证了上面说的 commit 与 git log 信息相反,rebase 的执行是按下图的执行顺序,除了能自动执行,都得进行 rebase --continue 继续下一个 action)

https://i.loli.net/2019/04/29/5cc6fc5b3e55e.jpg

退出后马上又进入了编辑器,还记得我们前面将第一条 action 改成了 reword 吗?这里提交我们需要修改的 commit(加上了file_4.txt)并保存退出

https://i.loli.net/2019/04/29/5cc6fc5e001eb.jpg

然后我们可以发现 rebase stopped at Add file_5.txt and file_6.txt 即 action 为 edit commit 并且 git log 中 Add file_3.txt and file_4.txt 已经成功合并

https://i.loli.net/2019/04/29/5cc6fc6162333.jpg

那么如何拆分 commit 呢?我们就需要修改本地文件重新提交,此时 git log 可以发现暂存区是空的,并已提交到代码仓库,为了测回提交,我们用 git reset HEAD^ 回退到上个状态

image.png

这时就可以重新进行 commit 提交啦

image.png

提醒

git rebase 用时一时爽,但切记黄金法则,在属于自己的分支上进行操作即可,如果在公共分支上进行 rebase,若你的队友本地已经有保存的副本,分支又被你改了,那就要注意人身安全了。