概述
本文浅讲一下 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日,文中内容可能已过时,请谨慎参考。