Git-Squash

最近实习的时候遇到这样的情况:本地开发的 branch 已经有多个 commit,而只需要提交部分 commit 去进行 code review, 经过一番搜寻发现 Git 里面 “还有这种操作”

由于整个过程还是有点复杂的,稍作记录如下

Git Squash 场景应用

首先值得一提的是,Git 本身其实有太多风骚的操作了,只是很多花里胡哨的内容平时用不少,于是也没有细细研究。

今天主要的场景如下:

  • 有多个历史 commit 需要合并处理
  • 提交部分的 commit(按时间顺序)

比如我们之前的文件和历史 commit 如下
此处文件内容是 0~5 每个数字一行,分别对应的 commit 记录也是对应的数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# git file content
0
1
2
3
4
5

# git commit log
d831adbf96fa024b01a71c893c828dce337424ca 5
ae743640e2eb34161cf830cf2a05907eb7cc494b 4
a0199792f738154105d40a1d0f1432ca965f8970 3
a9a7cbf6210ea012d8613503c00bb2c1e80b4de0 2
87c897c57e69227a04a7a8e56910f357979ff8e9 1
1ed67ad8183bcba715389280b1ec79abaf629725 init 0

commit 合并

比如我们的目标是:把第 4 次和第 5 次 commit 的内容合并,同时在 commit 记录上 有所体现
此时需要进行的操作是

1
git rebase -i 1ed67ad8183bcb

意为以 init 0 这个 commit 为基准进行一系列的修改操作
此时很神奇的是,会进入一个类似 vim 的 interaction 界面😂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
pick 87c897c 1
pick a9a7cbf 2
pick a019979 3
pick ae74364 4
pick d831adb 5

# Rebase 1ed67ad..d831adb onto 1ed67ad (5 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 代表选择这条 commit 记录(需要注意的是,如果没有保留 pick xxx,那么这条 commit 就会消失掉(:з」∠)
squash 是最重要的一项,代表可以把该 commit 压进之前的一个 commit 里面
由于我们 rebase 的 commit 是从 init 0 开始的,因此可选的范围是 commit 记录 1~5
相应的我们做如下的修改

1
2
3
4
5
pick 87c897c 1
pick a9a7cbf 2
pick a019979 3
pick ae74364 4
squash d831adb 5

然后和 vim 操作一样,进行 :wq 保存

注释修改

然后我们便进入如下的界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# This is a combination of 2 commits.
# This is the 1st commit message:

4

# This is the commit message #2:

5

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Sat Jun 24 20:37:07 2017 -0700
#
# interactive rebase in progress; onto 1ed67ad
# Last commands done (5 commands done):
# pick ae74364 4
# squash d831adb 5
# No commands remaining.
# You are currently editing a commit while rebasing branch 'master' on '1ed67ad'.
#
# Changes to be committed:
# modified: git-file
#

对应的没有注释的部分就是我们可以添加/修改的内容
比如我们改成

1
2
3
4
5
6
7
8
9
10
# This is the 1st commit message:

4 + 5

# This is the commit message #2:

# 5

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

此时再查看 git log 就会看到如下信息

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
28
29
commit e1f62d9b3a7ac741a6759cbc37485394a3b9f87a
Author: ...
Date: Sat Jun 24 20:37:07 2017 -0700

4 + 5

commit a0199792f738154105d40a1d0f1432ca965f8970
Author: ...
Date: Sat Jun 24 20:36:58 2017 -0700

3

commit a9a7cbf6210ea012d8613503c00bb2c1e80b4de0
Author: ...
Date: Sat Jun 24 20:28:39 2017 -0700

2

commit 87c897c57e69227a04a7a8e56910f357979ff8e9
Author: ...
Date: Sat Jun 24 20:28:29 2017 -0700

1

commit 1ed67ad8183bcba715389280b1ec79abaf629725
Author: ...
Date: Sat Jun 24 20:28:00 2017 -0700

init 0

至此,我们的基本目标已经达到

Others

以上场景不过只是小试牛刀,实际上 git rebase 还有太多的操作等待一一挖掘了
值得注意的是,这样的 reorder commit 不见得对所有情况都适用,一般把相邻的 commit 合并是没有问题的,但是在文件数目较多,commit 较多的时候,可能会出一些问题

以及上学期上了 CC 果然没时间更新 blog 了,有关 HBase 的内容其实也有很多值得总结的,看实习完后有时间再整理一篇好了 :)

Edited on 20191109
说来也真是搞笑 不知道为啥已经用了 Git 但这篇确实就是莫名其妙地搞不见了
最后找半天从很早以前的 GitHub 库里找回了原始的 md 文件
但愿天堂没有 GitHub 哈哈哈哈

谢谢投食 _(:з」∠)_