如何修改git中已经提交的内容

今天在git上提交代码的时候,不小心在 commit message 中打了几个错别字,merge、push 完了才发现。。 由于我的完美主义加强迫症比较严重,那几个错别字越看越不顺眼,寻思着把它们给改过来。一番资料搜寻和操作,成功搞定!

如何修改某次提交的 commit message

需要注意的是:没有办法修改整个项目的第一条日志。第2次以后的信息都可以通过此方法修改。

step 1. 查看提交的 commit id (SHA值)

如果 push 过,可以在git托管平台(比如 github、gitlab)上的 commits 里面看到(那串40位的编码就是了),只需要其前7位。
或者直接通过 git log 命令查看:

1
git log --oneline

在展示的结果上每条 log 记录的前面的字段就是我们需要的 SHA 值。

1
2
3
4
5
6
$ git log --oneline
b8b2df7 (HEAD -> master, origin/master) 中文
dd09519 di sici tijiao
f1d9380 english only modify again..
ea8a3b5 nonono correct message
66a4488 need to be changed message

比如我要修改的那条 commit 的 SHA 为:dd09519
那我需要的是这一条之前的一条 commit 的 SHA :f1d9380

step 2. 通过 git rebase 命令回到要修改提交的上一次提交的基础上

1
git rebase -i f1d9380

等待一会,然后会打开 vim 编辑器,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
pick dd09519 di sici tijiao
pick b8b2df7 中文

# Rebase f1d9380..f52c471 onto f1d9380 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# 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

在编辑器中找到你要修改的那个提交信息,用 i 命令进入编辑,
将那一行开头的 pick 改为 edit: pick dd09519 di sici tijiao -> edit dd09519 di sici tijiao
然后 esc -> : -> wq, 保存退出。

然后界面显示如下:

1
2
3
4
5
6
7
8
9
$ git rebase -i f1d9380
Stopped at dd09519... di sici tijiao
You can amend the commit now, with

git commit --amend

Once you are satisfied with your changes, run

git rebase --continue

step 3. 修改 commit message:

1
git commit --amend

再次进入 vim 编辑器,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
di sici tijiao

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Tue Sep 11 18:49:29 2018 +0800
#
# interactive rebase in progress; onto f1d9380
# Last command done (1 command done):
# edit 4df3762 中文信息 sici tijiao
# Next command to do (1 remaining command):
# pick f52c471 中文
# You are currently editing a commit while rebasing branch 'master' on 'f1d9380'.
#
# Changes to be committed:
# modified: README.md
#

可以看到第一行就是要修改的 commit message。
同样的通过 vim 命令 进入编辑模式,修改提交信息: di sici tijiao -> 中文信息 sici tijiao
然后:wq 保存退出。

1
2
3
4
$ git commit --amend
[detached HEAD 4df3762] 中文信息 sici tijiao
Date: Tue Sep 11 18:49:29 2018 +0800
1 file changed, 0 insertions(+), 0 deletions(-)

step 4. 完成 rebase:

1
git rebase --continue

等待一会,然后出现:

1
2
$ git rebase --continue
Successfully rebased and updated refs/heads/master.

表明操作成功。

step 5. 将修改后的变动 push 到远程

1
git push origin master -f

注意一定要使用 -f 参数,表示强制推送。
因为我们没有产生新的 commit(用 git status 可以看出),直接 push 不会发送任何东西。

step 6. 现在我们去远程仓库刷新下 commit 记录,可以看到 commit 信息就已经修改了。

最后,我们再来看下我们的日志信息

1
git log --oneline

细心点就会发现,从我们修改的那条 commit 起,之后的所有的 commit 的 commit id 都发生了变化!我修改的那条,由 dd09519 变成了 4df3762; 而它之后的那条记录也由 b8b2df7 变成了 f52c471 虽然我没由修改这条 commit 信息。

git log --oneline
1
2
3
4
5
f52c471 (HEAD -> master, origin/master) 中文
4df3762 中文信息 sici tijiao
f1d9380 english only modify again..
ea8a3b5 nonono correct message
66a4488 need to be changed message

BTW 还要说一个要注意的

就是如果 commit 信息要输入中文,记得用 git bash。因为我是在 IDE(webstorm)上进行的 commit,用的中文(要不怎么有错别字呢),那在修改 commit 信息的时候,我仍想用中文,我用 cmd、powerShell、Cmder,都试了,没法在 vim 里面敲中文,直接乱码,查资料改配置(quotepath = false、[gui] encoding = utf8)等等都没用,最后怀着绝望的心情,试了下 git bash, 居然中文支持的非常好!真是。。

另外,在查资料的过程中,还顺便 get 到几个 git 的高级技能。总结如下:

1. 修改最近一次的提交

方法一:commit –amend

这种方法不仅可以修改 commit message,也可以修改提交内容。这种方式在还没有推送到远端的情况下,可以保持原有的 Change-Id(commit id)。若已经推送到远端,Change-Id 则会修改掉。

1
2
3
4
5
# 修改需要修改的项目代码(如果只需要修改 commit message 就不用做)
git add . #如果只需要修改 commit message 就不用做
git commit --amend
# 在出现的 vim 编辑器中修改 commit message,保存退出。
git push <remote> <branch> -f #若还没有推送到远端,就不用做

方法二:reset

这种方法也可以修改提交内容和 commit message。这种方式在还没有推送到远端的情况下,也可以保持原有的 Change-Id(commit id)。若已经推送到远端,Change-Id 则会修改掉。

1
2
3
4
5
git reset HEAD^
# 修改需要修改的项目代码(如果只需要修改 commit message 就不用做)
git add . # 如果只需要修改 commit message 就不用做
git commit -m “new commit message”
git push <remote> <branch> -f # 若还没有推送到远端,就不用做

2. 提交到了错误的分支上的处理

方法一:reset + stash

1
2
3
4
5
6
7
8
9
# 取消最新的提交, 然后保留现场原状
git reset HEAD~ --soft
git stash
# 切换到正确的分支
git checkout name-of-correct-branch
git stash pop
git add .
git commit -m "new commit message"
# 现在你已经提交到正确的分支上了

方法二:cherry-pick 摘樱桃

1
2
3
4
5
6
git checkout name-of-correct-branch
# 把主分支上的最新提交摘过来~
git cherry-pick master
# 再删掉主分支上的最新提交
git checkout master
git reset HEAD~ --hard