概述
本文浅讲一下 Git 是如何压缩 commit 的。
操作
今天同事突然问我,由于在给同事的开源项目提 pr 的时候,自己比较长时间没有 rebase 同事的项目 master 分支了,而自己提交的 commit 又很多,有些 commit 又是实验性质的,乱七八糟的(其实就是没有用熟 git……),还有不少和其他同事的代码冲突了。提交代码的时候,同事希望精简一下 commit 否则其他人在看项目的演进的时候会一头雾水的。
我认为同事说的是对的,当然也存在一个问题就是同事没有用熟 git,因为在我们在版本管理的时候,其实每个 commit 都是有一定意义的,commit 不应该成为实验性质的一个动作。
回到同事的问题,「精简一下 commit」,那么好几个 commit 如何进行压缩呢?当然是有办法的。下图是为了演示所提交的三个 commit。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
* commit c4bf6724a039b524edeca2489086fbed0c4b5a0d
| Author: Oscar <runzhliu@163.com>
| Date: Mon Jun 11 11:02:33 2018 +0800
|
| [add] third commit
|
* commit a7e9aa4654e7f7d99ba530211e056a55314a3fff
| Author: Oscar <runzhliu@163.com>
| Date: Mon Jun 11 11:01:35 2018 +0800
|
| [add] second commit
|
* commit 0350222da791e26d07a4e77060709700cb48608d
Author: Oscar <runzhliu@163.com>
Date: Mon Jun 11 11:01:17 2018 +0800
[add] first commit
|
可以利用 git rebase 来实现本文所说的压缩 commit。-i 是代表 let the user edit the list of commits to rebase,这是在 git rebase -h 抄过来的,所以为什么是 -i 呢?就是因为我们需要编辑之前提交过的 commit。
1
|
git rebase -i <指定的 commit>
|
当我们指定到第一个 commit 的时候,我们可以编辑 a7e9aa4 还有 c4bf672 两个节点。具体命令的含义,在操作的清单上已经列举没明显了,有兴趣的可以逐个命令进行测试。这里我选择 squash。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
pick a7e9aa4 [add] second commit
pick c4bf672 [add] third commit
# Rebase 0350222..c4bf672 onto 0350222 (2 commands)
#
# 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
# d, drop = remove commit
#
# 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
|
以下是编辑最后的情况,把第三个节点压缩到第二个节点,并且保留第二个节点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
pick a7e9aa4 [add] second commit
squash c4bf672 [add] third commit
# Rebase 0350222..c4bf672 onto 0350222 (2 commands)
#
# 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
# d, drop = remove commit
#
# 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
|
压缩完后,需要重新编辑一下 commit 信息。
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
|
# This is a combination of 2 commits.
# This is the 1st commit message:
[add] second commit
# This is the commit message #2:
[add] third commit
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Mon Jun 11 11:01:35 2018 +0800
#
# interactive rebase in progress; onto 0350222
# Last commands done (2 commands done):
# pick a7e9aa4 [add] second commit
# squash c4bf672 [add] third commit
# No commands remaining.
# You are currently editing a commit while rebasing branch 'master' on '0350222'.
#
# Changes to be committed:
# new file: b.txt
# new file: c.txt
#
|
最后压缩成功的提示。
1
2
3
4
5
6
7
|
# git rebase -i 0350222da791e26d07a4e77060709700cb48608d
[detached HEAD 51c5f09] [add] second commit
Date: Mon Jun 11 11:01:35 2018 +0800
2 files changed, 1 insertion(+)
create mode 100644 b.txt
create mode 100644 c.txt
Successfully rebased and updated refs/heads/master.
|
自此,就完成了压缩多个「无意义」节点的需求了。操作简单,但是在我看来这不应该成为经常性的操作。因为在提交代码的时候,为了展示更加清晰的演进图,应该处理好自己的 commit 信息,主动去避免冗余。
警告
本文最后更新于 2017年2月1日,文中内容可能已过时,请谨慎参考。