今天同事突然问我,由于在给老大的开源项目提 pr 的时候,自己比较长时间没有 rebase
的老大的项目 master
分支了,而自己提交的 commit
又很多,有些 commit
又是实验性质的,乱七八糟的(其实就是没有用熟 git…),还有不少和老大的代码冲突了。提交代码的时候,老大要求精简一下 commit
否则其他人在看项目的演进的时候会一头雾水的。
我认为老大说的是对的,当然也存在一个问题就是同事没有用熟 git,因为在我们在版本管理的时候,其实每个 commit
都是有一定意义的,commit
不应该成为实验性质的一个动作。
回到老大的问题,「精简一下 commit
」,那么好几个 commit
如何进行压缩呢?当然是有办法的。
下图是为了演示所提交的三个 commit
。
* 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
。
➜ git-compress git:(master) git rebase -i <指定的 commit>
当我们指定到第一个 commit
的时候,我们可以编辑 a7e9aa4
还有 c4bf672
两个节点。具体命令的含义,在操作的清单上已经列举没明显了,有兴趣的可以逐个命令进行测试。这里我选择 squash
。
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
以下是编辑最后的情况,把第三个节点压缩到第二个节点,并且保留第二个节点。
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
信息。
# 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
#
最后压缩成功的提示。
➜ git-compress git:(master) 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
信息,主动去避免冗余。