2022年8月17日
# 前言
今天工作上遇到一个问题,说是需要将多次 commit 合并成一个 commit,好严格噢,但是其实这个也很简单。
最开始我以为要使用 git reset,可能也行,但是不太友好,需要重新 commit。
之后我以为要使用 git chery-pick,但是他会生成一个新的合并记录,也不符合这个严格的要求。
后来发现,原来是要使用 git rebase 才行。
git reabse 不仅可以将多个 commit 合并成 1 个,还可以把自己移动到某一个 commit 的前面,这种移动等同于 merge,如有冲突也需要解决。
# git rebase 将多个 commit 合并成 1 个
git reabse -i HEAD~4
,4 表示从当前的 commit 开始,往前合并 4 条(自己也算一条)。
这时候会出现一个交互式的编辑界面,需要你懂些 vi/vim 的基本命令,比如 i
、esc
、:
、wq
。
编辑界面出现后,会出现多条 commit 列表,下面会有英文说明注释的,但是不那么好懂。
pick xxx111xxx11xx commit-message-001
pick xxx222xxx22xx commit-message-002
pick xxx333xxx33xx commit-message-003
pick xxx444xxx44xx commit-message-004
# pick:保留该commit(缩写:p)
# reword:保留该commit,但我需要修改该commit的注释(缩写:r)
# edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
# squash:将该commit和前一个commit合并(缩写:s)
# fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
# exec:执行shell命令(缩写:x)
# drop:我要丢弃该commit(缩写:d)
从上述的内容可知,我想要合并成 1 个,我的做法是这样的也就是,让后面三个和第一个合并。
pick xxx111xxx11xx commit-message-001
s xxx222xxx22xx commit-message-002
s xxx333xxx33xx commit-message-003
s xxx444xxx44xx commit-message-004
上述的保存之后,之后会出现以下的内容。
# xxx111xxx11xx
commit-message-001
# xxx222xxx22xx
commit-message-002
# xxx333xxx33xx
commit-message-003
# xxx444xxx44xx
commit-message-004
你只需要删除其它的 commit message,只保留你要留下的那一个 commit message 即可。
# xxx111xxx11xx
commit-message-001
这个时候,你再 git push -f 一下,就能把你之前那几次的 commit 变成一个了。
注意:
如果你前面几次的记录有一个或者几个都在远程分支上,那么可能就需要特殊处理一下。比如我是把当前最新的 commit 提交上去,然后就 ok 了,而在之前我怎么 rebase 也不太行。
如果这个过程中出错了,你可以使用 git rebase --abort
# git rebase 将当前 commit 移动到其它的 commit 上去
这个操作是在你拉取一个分支 develop 后,你在这个分支上又创建了一个新分支,然后你在这个新分支上开发了两周,而原来那个 develop 分支已经提交了几十个 commit 了,这个时候默认都是 merge 一下,但是这会生成一次 merge 记录。
其实可以通过 rebase 将你当前分支移动到 develop 分支的上面去,不会产生一次 merge 记录,非常的优雅,但是还是得解决冲突噢。
# 切到develop分支,然后创建自己的分支
git checkout develop
git checkout -b feat/m2
git add .
git commit -m "feat(xxx): message-001"
# 切换到develop分支,然后拉取最新的记录,再切换回自己的分支,开始将自己的分支移动到最新的记录上,然后解决冲突,重新add、rebase continue,最后移动成功
git checkout develop
git pull
git checkout feat/m2
git rebase develop
操作:解决所有冲突
git add .
git rebase --continue
所有冲突解决完毕,那就移动成功。
# 结语
这个操作很久很久之前做过,但是和 git chery-pick 一样没咋用就给忘记了,现在把他捡起来,所以做一下记录。
我是看了半篇这个文章 (opens new window)后才回忆想起来。