Git rebase 合并多次提交

在一般研发管理流程中,我们一般都是这么使用Git版本的:

  • 0、先拿到一个需求(不细谈需求前面的采集、归纳整理、确认及评审等环节)
  • 1、从主分支checkout一个新分支
  • 2、在完成阶段性的目标后,提交代码
  • 3、完成整体需求后自测,并提测,提测内容包含当前分支代码
  • 4、通过测试后,代码合并到主分支
  • 5、新建tag,按照tag发布代码,系统上线

整个流程没有什么问题,只是在git管理时,会在git的提交记录中看到每一次的提交,使得主分支的版本比较多,在特殊情况下,进行代码回溯及比较时,弄得头晕眼花。

Git提供reabse命令,可以将多次commit合并成一个提交,这样提交记录看起来比较简洁些。

没有rebase的示例

开发改需求时,先checkout出了一个新分支feature_connectLimit_20201119,使用git log或者IDEA查看某需求的提交记录,如下图
Git rebase 合并多次提交
从上到下对应的revision number如下表

9e1a88efb9cad48a46a1103a6920d752afca3513
9a32e0bc33c8d31bb6d9f2150af247aa784df14d
9fa7517460aac5c8d3e617be0e8c92d3e0570926
d1fcf3db8a49207a065624295121b903d06bec64
d0096d69986a70ea7911dd521fcfafcd7dad13e0
2fe0e3f1ac36d6299bb2618394d0d73ab79e17c7
37a19607401bbe929884ae36d34f0df450754692

合并到主分支(main)时,如果不进行处理,就会在主分支看到6条commit,如下图
Git rebase 合并多次提交
以上还是比较乐观的情况,主分支只需要fast-forward到最新commit即可。如果发生冲突,再进行merge后,版本图表就不是一条简简单单的直线了。

rebase示例

git 提供了reabase命令,可以将(连续的、关联性的)多次commit合并成一个新的commit,再重新合并到主分支。

我们将2fe0e3f1~9e1a88ef这6个commit合并成一个新的commit。
具体看以下命令:

git checkout feature_connectLimit_20201119
git rebase -i 37a19607

其中,-i 的参数是不需要合并的 commit 的 hash 值。
进入到vi的编辑模式,

pick 2fe0e3f1a --story=1038913 --user=xxx 国内外 - 限制过去60分钟内呼叫短信次数 https://www.tapd.cn/xxx/s/xxx
pick d0096d699 呼叫记录:插入时检查重复
pick d1fcf3db8 呼叫记录:根据redis插入时检查重复
pick 9fa751746 --story=1038913 --user=xxx 国内外 - 限制过去60分钟内呼叫短信次数 https://www.tapd.cn/xxx/s/xxx
pick 9a32e0bc3 代码还原
pick 9e1a88efb 调整缓存key

# Rebase 37a196074..9e1a88efb onto 9fa751746 (6 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell

可以看到其中分为两个部分,上方未注释的部分是填写要执行的指令,而下方注释的部分则是指令的提示说明。指令部分中由前方的命令名称、commit hash 和 commit message 组成。

根据命令注释,我们很容易知道 pick 和 squash 这两个命令的大概意义。

pick 的意思是要会执行这个 commit
squash 的意思是这个 commit 会被合并到前一个commit

我们将 d0096d699~9e1a88efb 这5个 commit 前方的命令改成 squash 或 s,然后输入:wq以保存并退出,如下

pick 2fe0e3f1a --story=1038913 --user=xxx 国内外 - 限制过去60分钟内呼叫短信次数 https://www.tapd.cn/xxx/s/xxx
s d0096d699 呼叫记录:插入时检查重复   
s d1fcf3db8 呼叫记录:根据redis插入时检查重复   
s 9fa751746 --story=1038913 --user=陈振想 国内外 - 限制过去60分钟内呼叫短信次数 https://www.tapd.cn/xxx/s/xxx
s 9a32e0bc3 代码还原   
s 9e1a88efb 调整缓存key

这时我们会看到新的commit message 的编辑界面,大概列举了要合并的commit的log信息。

# This is a combination of 6 commits.
# This is the 1st commit message:

--story=1038913 --user=xxx 国内外 - 限制过去60分钟内呼叫短信次数 https://www.tapd.cn/xxx/s/xxx

# This is the commit message #2:

呼叫记录:插入时检查重复

# This is the commit message #3:

呼叫记录:根据redis插入时检查重复

# This is the commit message #4:

--story=1038913 --user=xxx 国内外 - 限制过去60分钟内呼叫短信次数 https://www.tapd.cn/xxx/s/xxx

# This is the commit message #5:

代码还原

# This is the commit message #6:

调整缓存key

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Fri Nov 20 19:08:02 2020 +0800
#
# interactive rebase in progress; onto 37a196074
# Last commands done (6 commands done):
#    squash 9a32e0bc3 代码还原
#    squash 9e1a88efb 调整缓存key
# No commands remaining.
# You are currently rebasing branch 'feature_connectLimit_20201119' on '37a196074'.
#
# Changes to be committed:
...file lists

输入新的提交信息,this is a rebase test for many times commit;,并:wq保存退出。再次查看 commit 历史信息,你会发现这些commit已经合并了。

这是合并的commit的提交信息:
Git rebase 合并多次提交
合并到主分支后,也只有一条commit,这些清爽多了。
Git rebase 合并多次提交

上一篇:git rebase branch 的理解


下一篇:git:将两个请求合并为一个请求