git merge 和 git rebase,如何选择?
嗨,你好啊,我是猿java
git 应该是当下代码管理最流行的工具,关于其两个重要的指令 git merge
和 git rebase
该如何使用也是争议颇多,这篇文章我们一起来聊一聊。
什么是 merge?
git merge
(合并)是一种将分叉的历史记录重新组合在一起的方法,在使用 git merge
时,当前分支将被更新,比如,将 B分支 merge 到 A分支,A分支就包含了 B分支的代码,但是 B分支不包含 A分支的代码。
git merge
通常与 git checkout
结合使用,用于选择当前分支,与 git branch -d
结合使用,用于删除过时的源分支。
如下示例,git merge
需要两个提交指针,并尝试找到两个分支之间的共同基础提交,一旦 git 找到一个共同的基础提交,它将创建一个新的“合并提交”,如下图:
合并后,我们在合并到的分支上有一个新的提交,此提交包含源分支中的所有更改。
什么是 rebase?
git rebase
(变基)是将一系列提交迁移或合并到新的基础提交的方式。
如下示例,我们通过从主分支 check
出一个另外一个分支的历史来了解 git rebase
的工作原理。
- 首先,我们从主分支上
check
了一个feature1
分支,并且在feature1
分支中添加了一些功能,然后进行了commit
提交; - 接着,从
feature1
分支再check
出feature2
,然后对feature2
分支也进行一些更改; - 最后,回到
feature1
分支并提交更多更改;
整个交互的流程图如下:
假如我们需要将 feature2
分支的更改合并到发布的 main
分支中,并且不希望包含 feature1
分支的更改,可以使用下面的指令:
1 | git rebase --onto main feature1 feature2 |
该指令用于重新定位 feature2
分支的基础,使其基于 main
分支,而不是 feature1
分支。这是通过将 feature2
分支上的提交应用到 main
分支之上来实现的。
指令执行结果如下:
feature2
分支的提交已重播到主分支上,feature2
分支现在包含主分支的所有提交以及 feature2
分支的新提交。
优缺点
接下来,我们一起来看看 git rebase
和 git merge
之间的优缺点。
git merge
优点
- 简单易用:git merge 命令通常比较直观,尤其是对于新手来说。
- 保留历史:git merge 会保留所有分支的原始提交历史,这对于追踪变化来源非常有帮助。
- 上下文保留:合并提交(merge commit)可以表明不同分支的合并点,保留了分支的上下文。
缺点
- 合并提交增加:每次合并都会生成一个新的合并提交,可能导致提交历史变得冗长。
- 复杂的历史结构:在多个分支并行开发时,合并后历史图表可能会变得复杂,难以阅读。
git rebase
优点
- 线性历史:通过 git rebase,提交历史变得更加线性,易于阅读和理解。
- 简洁清晰:没有额外的合并提交,提交历史更简洁。
缺点 - 历史重写:git rebase 会重写提交历史,这在多人协作时可能导致冲突和混淆。
使用 rebase的风险
与 git merge
相比,大多数人对使用 git rebase
犹豫不决。
git rebase
和 git merge
的基本目的是相同的,即它们帮助我们将更改从一个分支引入另一个分支。不同之处在于 git rebase
会重写提交历史记录,比如下图:
当多个开发人员在同一分支上工作时,直接使用 rebase
可能会导致混淆和冲突,因为每个开发人员会不断地重播和合并更改。下面示例进行解释:
假设你和另一位开发人员在名为 login_branch
的功能分支上合作。如果两人都直接对 login_branch
使用 rebase,那么在合并更改时会频繁发生冲突,为了避免这个问题,开发人员应从公共分支进行 rebase 。当公共分支变得稳定后,再将其中一个开发人员的 rebase 合并到主分支。
总结
- rebase 会在新基础之上重播提交。
- rebase 通过创建新的提交来改写历史记录。
- rebase 保持 Git 历史记录干净。
关键点
- 仅对您自己的本地分支进行
git rebase
操作 。 - 不要对公共分支进行
git rebase
操作。 - 使用 git reflog 撤消
git rebase
操作。
如何选择?
选择 git merge
还是 git rebase
取决于团队的工作流和偏好,以下是一些优化建议:
- 团队协作
小团队或个人项目:git rebase
可以帮助保持提交历史简洁。
大团队或多人合作:git merge
保留提交历史,避免重写历史带来的冲突。 - 代码审查
代码审查工具:可以使用代码审查工具(如 GitHub Pull Requests)来审查合并分支前的提交,这样即使使用 git merge 也能清晰地了解每个特性的提交历史。 - 混合使用
专题分支使用rebase
:在个人开发的专题分支上使用git rebase
,保持历史清晰。
整合分支使用merge
:在将专题分支合并到主分支时使用git merge
,保留上下文信息。 - 命名和注释
良好的提交信息:无论使用哪种策略,确保提交信息清晰、有意义,可以帮助理解历史。
合并提交注释:在使用git merge
时,可以在合并提交中详细描述合并的内容和目的,保留上下文信息。
总结
git merge
和 git rebase
都是 git 比较重要的指令,两个指令并没有绝对的好,也没有绝对的不好,平时使用时一定要注意每个指令的优缺点以及团队的抉择。
关于 git的更详细分析,参考往期文章: 美团一面:Git 是如何工作的?(推荐阅读)
参考资料
学习交流
如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。