Git merge 和rebase的区别

转载来源:
https://www.cnblogs.com/lyy-2016/p/6511930.html
https://www.jianshu.com/p/5c9c6383aa36
https://blog.csdn.net/wangnan9279/article/details/79287631

git rebase 和git merge 做的事其实是一样的。它们都被设计来将一个分支的更改并入另一个分支,只不过方式有些不同。

merge

实际工作中你可能经历以下步骤:
1.为了实现系统的新需求,你要创建一个新分支
2.突然发现主分支上有bug,你要新建一个分支来解决这个bug
3.分支上的bug解决后,你要切换到主分支合并bug分支
4.切换到最初的分支上,继续工作
merge的流程
转载来源:https://www.cnblogs.com/lyy-2016/p/6511930.html
1.master已经有了一些提交,提交版本如下,并且当前版本在c2上
在这里插入图片描述
2.为了解决#53问题,需要新建一个分支并切到该分支上:

git checkout -b iss53

在这里插入图片描述
3.iss53分支不断推进,并有紧急问题出现
对iss53问题进行了一些提交,分支在不断的向前推进
在这里插入图片描述
此时你收到消息,有个其他问题也要解决,你不必将这个紧急问题与iss53的修改混在一起,你只需要切回master分支

git checkout master

注意:当你切换分支的时候,git会重置你的目录,使其看起来像是回到了你在那个分支上最后一次提交的样子。Git 会自动添加、删除、修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样。
为了修复这个紧急问题,你需要再建一个分支,直到问题解决

git checkout -b hotfix

注意:你可能会在合并结果中看到"快进"(fast-forward)。由于当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,所以 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
现在,最新的修改已经在 master 分支所指向的提交快照中,你可以着手发布该修复了
在这里插入图片描述
5.master被快进到hotfix
由于被紧急问题打断,现在你需要回到之前的工作,可以删除掉hotfix分支

git branch -d hotfix

切换到之前的分支继续工作

git checkout iss53

在这里插入图片描述
此时如果你想要拉去之前hotfix的修改,你可以使用git merge master命令将master分支合并到iss53中;或者将iss53完成后,将其合并到master分支上。

6.将iss53合并到master上

git checkout master
git merge iss53

注意,虽然命令行和之前合并hotfix时是一样的,但是结果看起来不一样
在这里插入图片描述
因为,master 分支所在提交并不是 iss53 分支所在提交的直接祖先,Git 不得不做一些额外的工作。 出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4 和 C5)以及这两个分支的工作祖先(C2),做一个简单的三方合并。
和之前将分支指针向前推进所不同的是,Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。 这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。

在这里插入图片描述
7.删除iss53分支

git branch -d iss53

merge时有冲突
如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。
git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件,找到这些文件,手动解决冲突就可以git commit来完成合并提交了

=============================================================
Git rebase
转载来源https://blog.csdn.net/wangnan9279/article/details/79287631
在当前分支上合并 master

merge命令

git checkout feature
git merge master

Merge 好在它是一个安全的操作。现有的分支不会被更改

Rebase命令

git checkout feature
git rebase master

它会把整个 feature 分支移动到 master 分支的后面,有效地把所有 master 分支上新的提交并入过来

但是,rebase 为原分支上每一个提交创建一个新的提交,重写了项目历史,并且不会带来合并提交

rebase的优点和缺点
优点

  • rebase最大的好处是你的项目历史会非常整洁
  • rebase 导致最后的项目历史呈现出完美的线性——你可以从项目终点到起点浏览而不需要任何的 fork。这让你更容易使用 git log、git bisect 和 gitk 来查看项目历史

缺点

  • 安全性,如果你违反了 rebase 黄金法则,重写项目历史可能会给你的协作工作流带来灾难性的影响
  • 可跟踪性,rebase 不会有合并提交中附带的信息——你看不到 feature 分支中并入了上游的哪些更改

交互式的rebase
交互式的 rebase 允许你更改并入新分支的提交。这比自动的 rebase 更加强大,因为它提供了对分支上提交历史完整的控制

一般来说,这被用于将 feature 分支并入 master 分支之前,清理混乱的历史。
命令事例

git checkout feature
git rebase -i master

它会打开一个文本编辑器,显示所有将被移动的提交:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

在这里可以编辑提交的记录,具体可以怎么编辑,见
https://blog.csdn.net/wangnan9279/article/details/79287631

保存后关闭文件,Git 会根据你的指令来执行 rebase

忽略不重要的提交会让你的 feature 分支的历史更清晰易读。这是 git merge 做不到的

rebase命令的流程
转载:https://www.jianshu.com/p/5c9c6383aa36
1.在dev1分支上,你提交了2个单,c1和c2。然后你在dev1分支上将master分支rebase到当前分支git rebase master。此时,如果master分支已经与remote/master做了同步,更新了2个来自其他人的提交,c3和c4。
场景描述
在这里插入图片描述
rebase会做如下操作:

  1. 把dev1分支上的c1和c2“拆”下来,并临时保存成c1’和c2’。git里将其称为patch
  2. 将master分支上更新的提交c3和c4合并进dev1分支上

rebase操作,拆分提交
在这里插入图片描述

3.将c1’和c2’,再按顺序接在c3和c4的提交后面,如果没有冲突,则rebase成功。此时c1’和c2’虽然和c1和c2的修改完全一样,但却已经不是原来的提交了,commit id已经变化了

连接patch
在这里插入图片描述
此时dev1分支包含master分支的所有commit,并且超前了两个commit。如果你现在切换至master分支,并执行git merge dev1操作,由于没有不同于dev1的提交,merge操作就不会产生merge commit了。此时推送代码,也只会有两个commit。同时,master分支树笔直前进,分支很清晰地展示一个个提交。并且,上述的更新和提交代码的过程,是在dev1分支上修改冲突的,相对来说会比在master分支上修改更安全,如果不小心改混了,也能通过切换回master分支来找到稳定代码。

在master分支上合并dev1分支
在这里插入图片描述
基于上述内容,可以使用如下流程来提交代码:

  • 在dev1分支上进行开发,然后commit提交,在dev1分支上生成一个提交单。
  • 切换到master分支,与remote/master分支同步。
  • 切换回dev1分支,将master分支rebase到dev1分支上,如果有冲突,修改冲突。rebase操作的冲突修改与merge不一样,修改完冲突后,保存进index,然后直接git rebase --continue即可,不用再多做一次提交
  • 切换回master分支,合并dev1分支,此时合并会非常顺畅。然后push

链接:https://www.jianshu.com/p/5c9c6383aa36
来源:简书
rebase的风险

之前提到,rebase会将当前分支的新提交拆下来,保存成patch,然后合并进其他分支新的commit,最后将patch接进当前分支。这是rebase对多条分支的操作。对于单条分支,rebase还能够合并多个commit单号,将多个提交合并成一个提交。

git rebase -i [commit id]命令能够合并(整改)commit id之前的所有commit单。加上-i选项能够提供一个交互界面,分阶段修改commit信息并rebase。

但这里就会出现一个问题:如果你合并多个单号时,一不小心合并多了,将别人的提交也合并了,此时你本地的commit history和远程仓库的commit history不一样了,无论你如何push,都无法推送你的代码了。如果你并不记得rebase之前的HEAD指向的commit的commit ID的话,git reflog都救不了你。

tips: 你可以push时带上-f参数,强制覆盖远程commit history,你这样做估计会被打,因为覆盖之后,团队的其他人的本地commit history就与远程的不一样了,都无法推送了。

因此,请保证仅仅对自己私有的提交单进行rebase操作,对于已经合并进远程仓库的历史提交单,不要使用rebase操作合并commit单。

rebase黄金法则
法则:

绝不要在公共的分支上使用它!

在你运行 git rebase 之前,一定要问问你自己「有没有别人正在这个分支上工作?」。如果答案是肯定的,那就不能rebase

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值