首页 > 其他分享 >Git rebase vs merge:应该用哪一个?

Git rebase vs merge:应该用哪一个?

时间:2022-12-10 19:44:55浏览次数:44  
标签:Git rebase merge git master commit 分支

目录
背景
已经有了 git merge,为什么还需要 git rebase?
一个不太妙的场景
一个更不太妙的场景
git rebase 派上用场
什么时候用 git rebase?
什么时候不能用 git rebase
参考链接
背景
上周是我第一次用 git rebase 这个命令。在此之前,如果要同步别的分支上的内容,用的都是 git merge。

git rebase 作为一个比较“高级”的 git 命令,很早就有耳闻,但也一直没真正搞懂过,每次一看到特别复杂的图解说明就放弃了。最近在公司的一个比较大、比较正规的项目上工作,就想还是把 git rebase 搞懂吧!能用的话就尽量用。搞懂之后发现其实一点儿也不复杂。

已经有了 git merge,为什么还需要 git rebase?
首先需要明确的一点是,从代码的层面来说,git rebase 实现的功能和 git merge 完全相同,都是把某个分支的代码同步到当前分支上。假设没有冲突或者采用相同的方式解决冲突,那么两个命令得到的结果在代码层面上是相同的。唯一的区别在 commit 历史上。

按理来说 git merge 应该是先发明出来的那个,用着不错,能解决问题,但如果只用 git merge 的话,commit 历史可能不太美观。

一个不太妙的场景
设想以下这个很可能出现的场景:

你基于 master 创建了一个新的分支 A;
你在分支 A 上开发,新增了一些 commit;
完成一些功能并通过测试之后,准备合并到 master 上了。但在步骤 2 期间,有一些其他分支已经合并到了 master,并且和你的代码有冲突。于是你不得不先用 git merge master 把 master 上最新的内容同步到分支 A 上并解决冲突。这就导致分支 A 上又多了一个 Merge branch 'master' into A 的 commit;
这时候终于可以向 master 提交 PR 了。在合并 PR 的时候,你没有选择 squash (压缩 commit),所以分支 A 上所有不存在于 master 上的 commit,都会被加入到 master 中。这其中也包括那个 Merge branch 'master' into A 的 commit。
长此以往,master 上可能就会有很多类似 Merge branch 'master' into A 的 commit!这可能会让 master 的 commit 历史非常混乱。

一个更不太妙的场景
其实我上面举的例子还不是最坏的。。现实世界中还可能出现更让人无奈的事。比如下面这个场景:

你来到一个非常大、非常严格的项目上开发。首先基于 master 创建了一个新的分支 A;
你在分支 A 上开发,并新增了几个 comit。本地测试没有任何问题,但尝试 push 到在 GitHub (或者 GitLab)上的代码库时却失败了,提示自动化测试没有通过;
经过一番折腾过后,你发现是因为 master 上已经有了新功能,是针对这部分功能的测试没有通过(多么荒唐的机制!但我不止一次碰到过这种事,之前我做测试的时候碰到过,现在做开发的时候仍然碰到了);
于是你不得不合并 master,分支 A 上就多了一个 Merge branch 'master' into A 的 commit;
这时候终于可以向 master 提交 PR 了。但你的 PR 会经过严格的 review,偏偏 review 的人在印度,反馈很慢,在两周的时间里(哈哈,别以为不可能,还有比这更长的),你针对他们挑出来的问题提交了一些新的 commit,但为了能够 push 成功,你不得不执行很多次 git merge master,生成了很多个 Merge branch 'master' into A 的 commit(真事。。);
如果这时候没有 squash 直接合并到 master 上,那 master 的 commit 历史里就会出现很多个 Merge branch 'master' into A 。。
这样一来,master 的 commit 历史就会更容易变得极为混乱了。。

git rebase 派上用场
如果把以上场景中所有的 git merge master 换成 git rebase master,就不会出现这个问题了(当然,如果合并 PR 的时候 squash 一下其实也可以)。

为啥呢?因为 git rebase master 会这样做:

把你自从创建分支 A 以来,提交的全部 commit 都拿走,保存起来;
把 master 上所有新的 commit 同步过来。这会是一个 fast-forward,完成之后目前分支 A 和 master 就一模一样了;
假设你有 3 个 commit,分别是 commit a、 commit b、 commit c。这时候会把 commit a 拿回来,如果和当前代码没有冲突还好,如果有冲突的话你就需要先解决冲突,然后重新 commit(也就是说,这个新的 commit 就不是之前的 commit a 了);
重复这个过程,依次分别把 commit b 和 commit c 拿回来,有冲突的话你需要解决冲突。
看到没有?这样做的好处是,你的分支上不会出现 Merge branch 'master' into A 这样的 commit 了!commit 历史会极为清晰友好。

换句话说,这就好比是:

让你基于最新的 master 新建一个分支 B;
把你在分支 A 上的新 commit 都 cherry-pick 过来(如果你不知道这个命令的话,可以简单理解为“拿过来”);
最后再用分支 B 替换 分支 A。
什么时候用 git rebase?
明白了 git rebase 的原理之后,就很好理解应该什么时候使用了。简单来说,如果你在自己的分支 A 上开发,需要同步 master (或者别的你需要提 PR 的分支)的代码,那么就应该用 git rebase 而不是 git merge。但也有例外,见下节。

如果是反过来,从 master 上收集分支 A 上的最新代码,那么还是应该用常规的 git merge。

什么时候不能用 git rebase
git rebase 虽然好,但有个致命的问题:它会修改既有的 commit 历史。

假设:

你在分支 A 上工作;
另一名合作的开发人员也把分支 A 拉到了他的本地;
你在本地的分支 A 上执行了 git rebase master,然后 push 到远程代码库(这个时候其实已经就出问题了,因为 rebase 修改了历史,push 会失败并提示你本地的分支和远程的已经 diverge 了。这时候需要 push -f 才行);
这时候对另一名开发人员来说,自己本地的分支 A 和远程的分支 A 就已经 diverge 了。这样会造成比较混乱的局面(我倒是没试过,但想想就很乱);
所以,如果你的分支已经被别人拉到本地了,那么就不能用 git rebase,而要用 git merge 了!

参考链接
When do you use Git rebase instead of Git merge?
Git branch diverged after rebase
————————————————
版权声明:本文为CSDN博主「倪琛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/VoisSurTonChemin/article/details/121058059

标签:Git,rebase,merge,git,master,commit,分支
From: https://www.cnblogs.com/gongxianjin/p/16972167.html

相关文章

  • 如何使用Github创建一个仓库
    创建仓库(对我来说,这是新建)点击这里的Createrepository:进入到这样一个界面:其中,Repositoryname,是我们即将创建完成的仓库名称;而这里:需要填写的是对仓库的相关描述,当然......
  • Git文件操作
    文件4种状态版本控制就是对文件的版本控制,要对文件进行修改,提交等操作,首先要知道文件当前在什么状态,不然可能提交了现在还不想提交的文件,后者要提交的没提交上。......
  • GitOps实践之kubernetes部署Argocd
    1.什么是Argocd1.ArgoCD是Kubernetes的一个声明性GitOps持续交付工具。2.应用程序定义、配置和环境应该是声明性的和版本控制的。应用程序部署和生命周期管理应自动化、可......
  • 自然语言处理nlp小姜机器人(闲聊) nlp_xiaojiang-996station GitHub鉴赏官
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • git如何删除远程分支,git常用快捷指令列表
    git代码仓库管理工具1.初始化本地仓库a) Git init<directory> 2.克隆一个远程仓库a) Gitclone仓库名eg:[email protected]:edadd/FE-AApppon.git......
  • git 之撤销commit文件 && 回退push的文件
    前言在日常工作之中经常遇到我们在commit(提交到本地仓库)中提交多的文件比如将我们自己的配置文件和自己私有的的依赖或者日志文件提交的本地仓库的,这是和不友好的,一旦pus......
  • git rebase VS git merge? 更优雅的 git 合并方式值得拥有
    写在前面如果你不能很好的应用Git,那么这里为你提供一个非常棒的Git在线练习工具(关注易先讯,获取更多内容),你可以更直观的看到你所使用的命令会产生什么效果另外,你在......
  • 浏览器无法访问Github
    好久不见!天气越来越冷了,人生信号越来越不好,已经出现雪花点儿了。bug笔记持续更新中~问题:浏览器打不开​​github.com/​​害~碰到点问题!浏览器最近打不开​​github.com/​......
  • jenkins集成shell与gitlab
    jenkins集成shell    故障:                     故障:  开发提交了代码,然后自动发布测试环境持续集成持续交付,自动部署一般都是测试环境进行,方便......
  • 开发工具系列005-Hexo + gitub搭建个人博客教程
    title:开发工具系列005-Hexo+Github搭建个人博客tags:-网络编程系列categories:[]date:2015-06-2813:12:131.0说明其实,搭建个人博客的技术方案有很多。......