rebase最佳实践

本文最后更新于:2022年4月15日 凌晨

rebase最常见的应用场景有两种,一是合并分支,做类似merge的处理;二是合并commit,把多个commit合并为一个commit记录

一、合并分支

如下场景,你从master拉取了开发分支feature/A,在该分支上提交了两个commit: add dadd e

。当你开发完时master多了一个同事的开发的c功能的commit。这时可以使用rebase做变基处理

首先切换到master,把同事的代码更新拉取到本地

1
2
$ git checkout master
$ git pull

git pull有冲突就解决冲突

然后切回自己的开发分支feature/A,进行变基

1
2
$ git checkout feature/A
$ git rebase master

变基具体做了什么呢?

实际上git会先把feature/A上commitmaster分支对比,把feature/A上不同于mastercommit取消掉,然后将其保存为patch文件,存放在临时文件夹.git/rebase

然后把master分支上的commit合并到feature/A上

image-20220415003639461

接着对.git/rebase下的每个commit,逐个合并到feature/A上,每个commit的合入都可能有冲突,需要手动解决冲突。解决后执行一下命令,完成当前commit的合入。重复这个步骤知道所有commit都合入,就完成整个rebase过程了。

1
$ git rebase --continue

最终得到

二、合并commit

实际上,如果你的commit数量比较多,那么做rebase处理时可能会比较痛苦,尤其是多个commit中还对同一文件做了修改。

试想一下如下场景:

你在4个commit中都对a文件的同一处做了修改,如果a文件和远端master的代码有冲突,那么在rebase依次将commit合入的过程中,你需要解决4次冲突!

解决办法是在rebase远端master分支前,先把本地上的commit合并成一个commit

执行命令(commit id为你最早提交的commit的前一个commit的哈希值)

1
$ git rebase -i <commit id>  // commit id为 add b的哈希值

执行后进入vi编辑模式,默认情况下为p(pick),保留commit。把需要合并的改为s(squash),执行后就会打包成一个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
s ca1c52da change a
s a092ef48 change b
s de84901a change a
s 8f23126c change a
s cf23a16c change a


# Rebase 5f2452b2..8f33126c onto 5f2452b2 (4 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.
#

你也可以直接指定合并最近的n次提交记录,效果和上面的是一样的。

1
$ git rebase -i HEAD~5 // 合并最近的5次提交

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!