前言
大家好,我是HoMeTown。
众所周知,在使用 git
进行项目版本管理中,当完成一个功能点的开发并将其合并到 dev
分支时,一般情况下我们会有两种方式进行合并:git merge
与 git rebase
,二者都是将一个分支新的commits,合并到另外一个分支上。但是从原理上,二者却截然不同,今天来聊聊二者的用法、区别以及使用场景。
读完本篇文章,你将获得以下收获:
- 了解git rebase 与 git merge的用法
- 了解git rebase 与 git merge的区别
- 了解git rebase 与 git merge的使用场景
场景
以我们在日常开发工作中最常见的dev
和feature
分支举🌰,你在feature
分支上开发,然后别的同学在dev
分支提交了新的commit,如下图所示:
现在你需要把dev分支上的新的提交记录(feat: dev添加文件dev.js)合并到你的feature中,一般就会用到这两个命令
- git merge
- git rebase
git merge
我们先来看看用git merge
如何合并,首先切换到feature
分支
git switch feature 复制代码
执行merge合并命令
git merge dev 复制代码
输入merge commit
合并`dev`分支到`feature`分支 复制代码
此时Git Graph显示如下:
从图中可以看出:
git merge会在feature分支中产生一个新的merge commit,然后将两个分支的history联系在一起,我们的合并目的也已经达到了(dev分支的代码 合并到 feature分支),并且不会产生破坏性的影响,对现有的分支更不会以任何方式更改。
同时,feature分支每次需要合并上游分支的提交时,都会产生一个额外的merge commit,如果merge request过于频繁,那么在feature分支上就会有很多的merge commit,会严重污染分支历史记录,如果很多人很多分支进行开发与merge,分支图就会变成泡面图:
git rebase
接下来我们再从dev分支切出一个新分支feat-a
git checkout -b feat-a 复制代码
在dev分支做一些改动,feat-a分支做一些改动,此时,Git Graph显示如下:
这块可能有点乱,我来解释一下:
首先按照时间点来看,dev分支是最后一个改动的,在蓝色的分支线。
feature分支由于dev分支提交了新的commit,feat-a提交了新的commit,被单独拎出来了一个绿色的分支线
feat-a从dev分支checkout出来之后,也做了新的commit,变成了一根红色的分支线
接下来使用git rebase把dev分支合并到feat-a分支上:
git siwtch feat-a git rebase dev // 如果有冲突解决冲突 git rebase --continue 复制代码
Git Graph如下:
可以看到:
rebase操作 将我们本地的feat-a分支
整个移动到了dev分支
的顶端
,有效的整合了所有的dev分支上的提交,但是,与 merge操作 有所不同的是,reabse操作 通过给原始分支中的每个提交创建新的commits来重写项目历史记录,从而达到在feat-a分支上线性提交的目的。
rebase操作 的好处是可以获得更清晰的历史记录,首先他消除了git merge产生的merge commits,其次,如你在图上看到的,rebase会产生一个线性的历史记录,你可以在feat-a分支上没有任何分叉的情况下,一直追寻到项目的first commit。
如果你有自己把前面我所讲的都试试,你会发现,我们本地分支和远程分支不同步了,你会想去把feat-a分支push到origin,但是却报错了,报错信息如下:
这是因为git的push操作默认是假设远端的分支和你本地的分支可以进行fast-forward
操作,换句话说就是这个push命令假设你的本地分支和远端分支的唯一区别是你本地有几个新的commit,而远端没有。
但是由于进行了rebase操作,现在本地的feat-a分支多了一个之前从没见过的commit,这种情况下是不能进行fast-forwad模式的合并操作的,所以当执行 git push origin feat-a 命令时会报错误。
要解决这个问题必须确保当前feat-a
分支只有你自己在开发,没有其他成员的操作,如果符合这一条件,那么可以直接进行强制推送,执行命令:
git push --force origin feat-a 复制代码
此时,远程feat-a
分支推送完成,可以看到,直线看着很舒服。
如果有其他人在这个分支上和你一起开发的话,使用命令:
git push --force-with-lease origin feature 复制代码
确保分支安全性。
git merge和git rebase的优缺点
- git merge
- 优点:不会破坏原分支的提交记录。
- 缺点:会产生额外的提交记录,并进行两条分支线的合并。
- git rebase
- 优点:无需新增提交记录到目标分支,reabse后可以直接将对象分支的提交历史加到目标分支上,形成线性提交历史记录,更加直观。
- 缺点:不能在一个共享分支上进行reabse操作,会带来分支安全问题。
git merge和git rebase的正确使用
- 合代码到公共分支的时候使用git merge,书写正确规范的merge commits留下记录。
- 合代码到个人分值的时候使用git rebase,可以不污染分支的历史提交记录,形成简介的线性记录。