0%

【Git学习】合并与修改 commit

合并多条commit

场景:

改完 bug 提交了 commit 之后发现没有改全, 需要再次修改提交, 但是一个 bug 不想有多条 commit

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git log
commit e47711f5633548b809b7e8f669d6fb608a84680e (HEAD -> master)
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:06:04 2020 +0800
duplicate commit
commit b7e411f6843b08aaa41ec68a7fdb2b241eb03fd0
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:05:55 2020 +0800
duplicate commit
commit 9c0c06c2478df556adce50fb26faf559424f8e78
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:02:31 2020 +0800
[ADD] 1.txt

存在两条 duplicate commit 的提交记录,需要进行合并。

选择 rebase 基点, 由于要合并的提交最早的是 b7e411f6843b08aaa41ec68a7fdb2b241eb03fd0,选取前一个做为 rebase 的基点

git rebase -i 9c0c06c2478df556adce50fb26faf559424f8e78

也可以使用 git rebase -i b7e411f6843b08aaa41ec68a7fdb2b241eb03fd0~1

在命令行中执行 rebase 命令后,默认会打开 vim 编辑器进行编辑, 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pick b7e411f duplicate commit
pick e47711f duplicate commit
# Rebase 9c0c06c..e47711f onto 9c0c06c (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
# b, break = stop here (continue rebase later with 'git rebase --continue')
# 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

需要注意的是,这里commit的显示顺序跟 git log 的默认显示顺序相反的

修改后的内容为:

1
2
pick b7e411f duplicate commit
f e47711f duplicate commit

检查修改, 出现 Successfully 就表示修改成功,再看 log 列表

1
2
3
4
5
6
7
8
9
$ git log
commit af1a6cdcacff2298a4a77355aae98bccbc3027b2 (HEAD -> master)
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:05:55 2020 +0800
duplicate commit
commit 9c0c06c2478df556adce50fb26faf559424f8e78
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:02:31 2020 +0800
[ADD] 1.txt

合并后新的 commit 则为 af1a6cdcacff2298a4a77355aae98bccbc3027b2, 如果觉得合并的不对,要进行重来一次,前面的 commit 就可以用上了,

使用 git reset 来进行回滚:

1
2
$ git reset --hard e47711f5633548b809b7e8f669d6fb608a84680e
HEAD is now at e47711f duplicate commit

推送新分支

由于 rebase 操作会修改版本树,如果合并的几个 commit 仅存在于本地,则直接 git push 推送即可

如果合并的几个 commit, 已经推送到远端了,则需要把本地的版本树覆盖掉远端,在 push 时使用 --force-f 参数来强推

1
git push -f origin 本地分支:远程分支

修改 commit 描述

在提交后,由于手残 commit 内容打错字了,强迫症看着不舒服。 分为两种场景:

  • 要修改的 commit 是最新的一次提交
  • 要修改的 commit 不是最新的一次提交

要修改的 commit 是最新的一次提交:

1
git commit --amend

修改描述后保存就可以了

要修改的 commit 不是最新的一次提交

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git log
commit 29dcff5fb5eb508bb63a8c79c942f1c23602edc5 (HEAD -> master)
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:06:04 2020 +0800
duplicate commit 1
commit b7e411f6843b08aaa41ec68a7fdb2b241eb03fd0
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:05:55 2020 +0800
duplicate commit
commit 9c0c06c2478df556adce50fb26faf559424f8e78
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:02:31 2020 +0800
[ADD] 1.txt

找到要修改的commitid: b7e411f6843b08aaa41ec68a7fdb2b241eb03fd0, 使用 ~1 来快速定位 rebase 的基点

1
$ git rebase -i b7e411f6843b08aaa41ec68a7fdb2b241eb03fd0~1

这里的操作跟合并提交的操作类似,不同的是需要使用修改的指令 r 或者 reword

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
r b7e411f duplicate commit
r e47711f duplicate commit
# Rebase 9c0c06c..e47711f onto 9c0c06c (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
# b, break = stop here (continue rebase later with 'git rebase --continue')
# 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

保存之后会依次进入 rcommit 的编辑界面,修改 commit 内容后保存退出

查看 git log 日志, 已经修改好了:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git log
commit e73d817c3158482eb4d27c0d1a0858eeeb1fb4cc (HEAD -> master)
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:06:04 2020 +0800
[ADD] 3.txt
commit 4d34a4ee66bcf7e818d48c4bdf87e3a7e01c149f
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:05:55 2020 +0800
[ADD] 2.txt
commit 9c0c06c2478df556adce50fb26faf559424f8e78
Author: lovehhf <853885165@qq.com>
Date: Thu Mar 19 21:02:31 2020 +0800
[ADD] 1.txt