问题背景:做新需求时,你从远程master分支,创建一个分支作为开发分支feature1,随着时间的推移,远程master分支上合入了同事的提交,你在开发分支上进行了一些提交(如图1),此时,若需要合入远程master最新的提交记录到当前分支,有两种合并策略,git merge 和git rebase,那么这两种有什么区别呢?应选择哪一个呢?
经过一系列修改提交,master指向了commit3的提交点,feature1分支指向commit5
- git merge
若执行git merge origin/master,此时,git整合了commit3,和commit5,产生了一个新的提交点commit6
用vscode的gitlen插件观察提交记录:
会发现多了一个提交记录:
以上是当master只有一个新提交的情况,而当master有多个提交记录时,feature1合并结果则是如下图:
不仅保留了master的所有提交记录,还有一个merge点。这是我们通常会碰到的情况,毕竟master经常会发生变动。
此时,可添加--squash, 即git merge origin/master --squash,用于将master上多个提交进行合并。查看提交记录:
(squash 合并为本次合并的commit信息)
可以看到,只有一个提交点,但还是产生一个提交点,将两个提交变成了一个。
但我只是想获取最新的master上的修改,并不希望它产生一个额外的提交记录,否则每一次落后了主分支master ,都要产生额外的合并的提交信息,会十分影响自己的分支记录,有没有办法呢? 答案就是rebase
2.git rebase
rebase 的作用就是把另一个分支的修改重放到当前分支。继续以上面例子为例,执行git rebase origin/master,查看git记录:
可以看到,feature1就像是直接将两个commit 拿了过来一样,没有产生任何额外的提交信息。也像是按照最新的master 拉取的分支一样,分支记录与master一致,只有feature自己产生的提交记录,看起来更加干净清爽。
以上所示例的,是本地分支merge 主分支的情况,还有主分支merge其他分支的情况,本质上都一样。只不过,公司里,通常是用可视化的git工具来简化代码合并操作,只需理解即可。对于我们开发者而言,更通常的是在本地进行一些合并操作。
一些补充:
git rebase 还可以用来合并多个提交:git rebase -i HEAD~3 即合并最近3次提交,命令最后的数字就是个数。这个操作也是经常可以用到的,可以在合并前让代码commit信息更简洁。
最后对git merge 和git rebase做个总结:
两个命令都是 Git 中的分支整合命令是 Git 中的分支整合命令。git merge 的作用是将一个分支(源分支)的更改合并到另一个分支(目标分支)中。执行 git merge 时,Git 会创建一个新的合并提交(merge commit),这个提交记录了两个分支合并的历史信息,将源分支的更改整合到目标分支。
git rebase 的目的是将一个分支上的更改“重放”到另一个分支上,使代码历史看起来像是在目标分支上直接进行的开发。
代码历史结构
- Git Merge:创建合并提交,保留分支的分叉和合并关系,代码历史呈现“分叉 - 合并”的结构。
- Git Rebase:重放差异提交,消除分支的分叉和合并提交,代码历史呈现线性结构。
对代码历史的影响
- Git Merge:保留完整的代码历史,包括分支的创建、分叉和合并过程。每个合并提交都记录了参与合并的分支信息,便于追溯和审查。
- Git Rebase:改变代码历史,将分支的更改序列移动到目标分支的最新提交之后。这可能会导致一些历史信息的丢失,因为原本的分支结构被重写。
适用场景
- Git Merge:适用于团队协作、代码审查和快速整合场景。它简单直接,能够清晰地展示分支之间的合并关系,便于团队成员理解和协作。
- Git Rebase:适用于个人开发、代码清理和维护线性历史场景。它能够创建整洁的代码历史,便于开发者理解和追溯代码的修改历程,但需要谨慎使用,以免影响团队协作。
安全性
- Git Merge:相对安全,因为它不会改变已有的代码历史。即使合并过程中出现问题,也可以通过查看合并提交来追溯和解决问题。
- Git Rebase:存在一定风险,因为它会重写代码历史。如果在公共分支上进行
git rebase,可能会导致其他开发者的工作出现问题,因为他们基于旧的历史进行了开发。因此,在公共分支上使用git rebase需要格外小心。