to inspire confidence in somebody.

0%

利用Git的Rebase功能合并一系列commits

工作中如果使用Git作为版本管理工具的话,应该经常会遇到因为各种原因一下提交了很多个commit的情况,比如添加一个功能,测试出问题继续commit修改,最后git log看提交历史就会变成这样:

1
# git log
2
commit 9995aafb7a597d9a7fcf9a341a731324813c5aad (HEAD -> master)
3
...
4
    Commit 4
5
6
commit 54062e7317fa19a228d8f4f63236467317c17672
7
...
8
    Commit 3
9
10
commit 1571ee6b861315ec46875fbececd46c9daaa5d04
11
...
12
    Commit 2
13
14
commit ae95aac116af934742e1dd2eca435a0d6e70b77f
15
...
16
    Commit 1
17
18
commit 3f0373c3afb9e9ffd6174b8244ec3e936d3583e0
19
...
20
    init

这样看起来不那么美观,也会一定程度上污染主分支,如果遇到问题,需要看diff的时候,也会不那么方便,所以介绍一个利用git rebase命令合并一系列commit的方法。

首先,需要确定要合并哪些commits,以上面的例子,假设我们需要合并Commit 1Commit 4这几个提交,那么,我们就要找到这几个提交的上一个提交的CommitID,也就是3f0373c3afb9e9ffd6174b8244ec3e936d3583e0

然后,我们执行git rebase -i 3f0373c3afb9e9ffd6174b8244ec3e936d3583e0,此时会弹出编辑器,让你选择针对这些提交做那些操作:

1
pick ae95aac Commit 1
2
pick 1571ee6 Commit 2
3
pick 54062e7 Commit 3
4
pick 9995aaf Commit 4
5
6
# Rebase 3f0373c..9995aaf onto 3f0373c (4 commands)
7
#
8
# Commands:
9
# p, pick <commit> = use commit
10
# r, reword <commit> = use commit, but edit the commit message
11
# e, edit <commit> = use commit, but stop for amending
12
# s, squash <commit> = use commit, but meld into previous commit
13
# f, fixup <commit> = like "squash", but discard this commit's log message
14
# x, exec <command> = run command (the rest of the line) using shell
15
# b, break = stop here (continue rebase later with 'git rebase --continue')
16
# d, drop <commit> = remove commit
17
# l, label <label> = label current HEAD with a name
18
# t, reset <label> = reset HEAD to a label
19
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
20
# .       create a merge commit using the original merge commit's
21
# .       message (or the oneline, if no original merge commit was
22
# .       specified). Use -c <commit> to reword the commit message.
23
#
24
# These lines can be re-ordered; they are executed from top to bottom.
25
#
26
# If you remove a line here THAT COMMIT WILL BE LOST.
27
#
28
# However, if you remove everything, the rebase will be aborted.
29
#
30
# Note that empty commits are commented out

可以看到最上面的4行,是需要执行的操作,在底下也有注释,每个提交前面的命令代表的含义,我们要用的命令是squash,即合并到前一个提交中去,当然也可以根据情况改成其他,这里就不说明了。

我们要做的是合并这几个提交,那就需要把需要合并的都替换成squash,像这样:

1
pick ae95aac Commit 1
2
squash 1571ee6 Commit 2
3
squash 54062e7 Commit 3
4
squash 9995aaf Commit 4

然后直接保存,如果一切顺利(没有冲突)的话,会直接弹出来Commit Message的编辑器,像这样:

1
# This is a combination of 4 commits.
2
# This is the 1st commit message:
3
4
Commit 1
5
6
# This is the commit message #2:
7
8
Commit 2
9
10
# This is the commit message #3:
11
12
Commit 3
13
14
# This is the commit message #4:
15
16
Commit 4
17
18
# Please enter the commit message for your changes. Lines starting
19
# with '#' will be ignored, and an empty message aborts the commit.
20
#
21
# Date:      Wed May 22 17:25:03 2019 +0800
22
#
23
# interactive rebase in progress; onto 3f0373c
24
# Last commands done (4 commands done):
25
#    squash 54062e7 Commit 3
26
#    squash 9995aaf Commit 4
27
# No commands remaining.
28
# You are currently rebasing branch 'master' on '3f0373c'.
29
#
30
# Changes to be committed:
31
#       modified:   README

可以看到几个commit message都在一起了,可以选择保留,也可以选择重新编辑,这里就都保留着,直接保存,就rebase成功了,再git log看一下,是不是变的清爽了?

1
# git log
2
commit 1cf7ca9baabf811573e3d46e8a1c33353d044fcd (HEAD -> master)
3
...
4
    Commit 1
5
6
    Commit 2
7
8
    Commit 3
9
10
    Commit 4
11
12
commit 3f0373c3afb9e9ffd6174b8244ec3e936d3583e0
13
...
14
15
    init