git rebase 和 git merge 是我们日常开发中使用的两种分支合并策略。两者所处理的问题是相同的,它们都能够将分支代码合并到主分支,就是将一个分支上的改动集成到另一个分支上,区别在于他们实现的方式不同。
考虑如下的工作场景:
你要在当前项目开发一个新的功能点,于是基于dev分支拉出了一个feat-a分支开始进行开发。而与此同时你的同事基于dev在在fixbug-1分支上修复了一个bug。现在需要合并feat-a 和 fixbug-1分支到dev分支。
这里先假设你的同事先行把已在fixbug-1分支修复完成的bug合并到dev分支上
# 切换到 dev分支上
git checkout dev
# 合并 fixbug-1 到dev分支
git merge fixbug-1
基于上面的预设场景,你已经在feat-a分支完成了功能开发,接下来我们分别使用 git merge 和 git rebase 来合并代码,具体看下会发生什么。
首先使用 git merge 进行合并
# 先拉取 remote 最新版本
git pull
# 切换到dev分支
git checkout dev
# 合并自己开发的功能分支
git merge feat-a
从上面的图中可以看到 feat-a分支合并到dev分支过程中,历史提交线中自动新增了一个提交(c6)称呼为合并提交。
使用 git rebase 进行合并
git rebase 仅从字面上来看:「rebase」是「re」加上「base」,翻译成中文大概是「重新定义分支的参考基准」的意思,一般我们简称为变基。
# 先拉取 remote 最新版本
git pull
# 切换到自己开发完成的功能分支feat-1上
git checkout feat-a
# 合并到dev
git rebase dev
从上面图中可以看到,执行 git rebase dev 命令后将原先在feat-a 分支上提交的 c2、c3两个提交记录复制到dev分支中(c2' 、c3'),并不会出现使用 git merge 合并时在历史提交现上产生多余的合并提交记录
上面我们分别使用了 git merge 和git rebase对分支进行合并,可以看到两者都实现了代码合并的目标,仅从目标结果来看两者是一致的,既然两者实际效果一样,那么实际工作中应该怎样选择使用呢?
git merge 和 git rebase 的选择
在怎样选择使用 git merge 和 git rebase 时,先了解下两者的优缺点
git merge
优点:
- git merge 合并操作比较直观
- git merge 会保留所有的分支历史和合并点
- 由于 git merge 不会改变现有的历史,它被认为是一种安全的操作
缺点:
- 频繁的合并会在项目历史中创建很多的合并提交,从而使历史变得复杂难以跟踪。
git rebase
优点:
- git rebase 使得历史记录看起来像是一条直线,没有分叉,从而便于理解项目的历史进展。
- 由于重写了提交历史,git rebase 通常可以减少分支和合并提交的数量。
- git rebase 可以避免在合并特性分支时产生额外的合并提交,避免不必要的合并提交。
缺点:
- git rebase 实质上是改写历史,如果对已经公开的分支使用,可能会引起混乱和问题
从上面可以看到,git merge 侧重完整、安全而 git rebase 侧重整洁, 了解到两者的优缺点后,我们期望项目的提交记录既要完整、安全、又要整洁。为此我们可以采用下面的 策略方法:
在个人的 feature 分支上工作时,定期使用 git rebase main 或 git rebase develop(取决于你的基础分支)可以保持你的分支更新,并避免将来与基础分支合并时出现大量的合并冲突。
当 feature 分支开发完成并准备并入主分支(如 main 或 develop)时,通常会使用 git merge。这样可以保留一个清晰的结构,说明何时以及为何将特定的功能并入主分支。
小结一下
git merge 和 git rebase 两者都可以用来合并分支, git merge 保留了真实的、时间线性的项目历史,清晰地表示了何时以及为何会并合并一个分支,并且它不会改变历史。git rebase 创建了一条线性的历史,让历史看起来更干净整洁。避免了不必要的合并提交。在某些情况下能更清晰的显示提交的顺序。可能会改变历史,因为它实际上是创建了新的提交。
通常建议在个人的本地分支上使用 git rebase 保持历史干净,在公共分支(像是主分支或发布分支)上使用 git merge 保持历史的真实性。
另外需要紧记:切记不要对已经推送到远程仓库的分支执行 rebase 操作,因为它会改变已经公布的历史,这会给其他开发者带来麻烦。
最后建议在工作中遵守这样的法则:公共分支使用 git merge 合并,本地分支使用 git rebase合并。