Git rebase和merge区别详解

这篇具有很好参考价值的文章主要介绍了Git rebase和merge区别详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

此文在阅读前需要有一定的git命令基础,若基础尚未掌握,建议先阅读这篇文章Git命令播报详版

在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase(变基),本文主要讲解rebase用法。

变基的基础用法

当开发任务分叉到两个不同分支,又各自提交了更新。

Git rebase和merge区别详解,GIT,git,github,前端

整合分支最容易的方法是 merge 命令。 它会把两个分支的最新快照(C3 和 C4)以及二者最近的共同祖先(C2)进行三方合并,合并的结果是生成一个新的快照(C5)并提交。

Git rebase和merge区别详解,GIT,git,github,前端

还有一种方法,你可以提取在 C4 中引入的补丁和修改,然后在 C3 的基础上应用一次。 在 Git 中,这种操作就叫做 变基rebase)。 你可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样。

在这个例子中,你可以检出 experiment 分支,然后将它变基到 master 分支上:

git checkout experiment
git rebase master

它的原理是首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master) 的最近共同祖先 C2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件, 然后将当前分支指向目标基底 C3, 最后以此将之前另存为临时文件的修改依序应用。

Git rebase和merge区别详解,GIT,git,github,前端

现在回到 master 分支,进行一次快进合并。将 C4 中的修改变基到 C3 上

git checkout master
git merge experiment

Git rebase和merge区别详解,GIT,git,github,前端

此时,C4’ 指向的快照就和 merge示例中 C5 指向的快照一模一样了。

这两种整合方法的最终结果没有任何区别,但是变基使得提交历史更加整洁。你在查看一个经过变基的分支的历史记录时会发现,尽管实际的开发工作是并行的,但它们看上去就像是串行的一样,提交历史是一条直线没有分叉。

一般我们这样做的目的是为了确保在向远程分支推送时能保持提交历史的整洁,例如向某个其他人维护的项目贡献代码时。在这种情况下,你首先在自己的分支里进行开发,当开发完成时你需要先将你的代码变基到 master 上,然后再向主项目提交修改。这样的话,该项目的维护者就不再需要进行整合工作,只需要快进合并便可。

请注意,无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。

变基过程中的冲突

在合并中,经常会出现冲突。在解决冲突后,执行如下命令:

git add .
git rebase --continue

如果冲突无法解决可以执行 git rebase --abort取消这次合并操作。

解决冲突后无法push问题

有过git rebase经验的同学都知道,多人协作并行开发时刚解决完一堆冲突后,松了一口气,push时又提示拒绝,用-f或者--force参数强制推送,发现就推送成功了。

提交失败的原因,我个人是这么理解的,使用 rebase 之后,experiment分支上比master分支上多的修改,直接“插入”到了master分支修改的内容之后,也就是 experiment 分支的修改在 master 分支上重演了一遍,相对远程 master 分支而言,本地仓库的master分支的“基底”已经变化了,直接 push 是不行的,所以确保没有问题的情况下必须使用 --force 参数才能提交。

但很多人可能忽略了一个问题: git push --force 是不安全的。

  • 生产过程中碰到过一次,rebase后强制push,同一分支的其他同学pull代码时出错,强行覆盖也不行。所以除非有充分的强制推送理由,其他情况下,不建议使用git push --force

  • 这里将推荐 --force-with-lease 参数,让我们可以更安全地进行强制推送,Git 的 1.8.5 版本开始提供了这个参数,旨在解决 git push --force 命令造成的安全问题。

关于git push --force-with-lease更加详细的可以自己查查,这里推荐一篇:Git 更安全的强制推送,–force-with-lease

更新变基后的代码

更新代码使用的是 git pull origin master --rebase 而不是 git pull origin experiment

git pull 这条命令默认使用了 --merge 的方式更新代码,如果你不指定用 --rebase,有的时候就会发现日志里有自己分支合并到了自己分支提交的提交记录。

更有趣的变基用法

在对两个分支进行变基时,所生成的“重放”并不一定要在目标分支上应用,你也可以指定另外的一个分支进行应用。 如下示例,你创建了一个主题分支 server,为服务端添加了一些功能,提交了 C3 和 C4。 然后从 C3 上创建了主题分支 client,为客户端添加了一些功能,提交了 C8 和 C9。 最后,你回到 server 分支,又提交了 C10。

Git rebase和merge区别详解,GIT,git,github,前端

假设你希望将 client 中的修改合并到主分支并发布,但暂时并不想合并 server 中的修改, 因为它们还需要经过更全面的测试。这时,你就可以使用 git rebase 命令的 --onto 选项, 选中在 client 分支里但不在 server 分支里的修改(即 C8 和 C9),将它们在 master 分支上重放:

git rebase --onto master server client

以上命令的意思是:“取出 client 分支,找出它从 server 分支分歧之后的补丁, 然后把这些补丁在 master 分支上重放一遍,让 client 看起来像直接基于 master 修改一样”。这理解起来有一点复杂,不过效果非常酷。

Git rebase和merge区别详解,GIT,git,github,前端

现在可以快进合并 master 分支了。(如图 快进合并 master 分支,使之包含来自 client 分支的修改):

git checkout master
git merge client

Git rebase和merge区别详解,GIT,git,github,前端

接下来你决定将 server 分支中的修改也整合进来。 使用 git rebase <basebranch> <topicbranch> 命令可以直接将主题分支 (即本例中的 server)变基到目标分支(即 master)上。 这样做能省去你先切换到 server 分支,再对其执行变基命令的多个步骤。

git rebase master server

如图 将 server 中的修改变基到 master 上 所示,server 中的代码被“续”到了 master 后面。

Git rebase和merge区别详解,GIT,git,github,前端

然后就可以快进合并主分支 master 了:

git checkout master
git merge server

至此,client 和 server 分支中的修改都已经整合到主分支里了, 你可以删除这两个分支,最终提交历史会变成图 最终的提交历史 中的样子:

git branch -d client
git branch -d server

Git rebase和merge区别详解,GIT,git,github,前端

变基的风险

变基也并非完美无缺,要用它得遵守一条准则:

如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。

变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。 如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你还要拉取并整合他们修改过的提交,事情就会变得一团糟。

让我们来看一个在公开的仓库上执行变基操作所带来的问题。 假设你从一个中央服务器克隆然后在它的基础上进行了一些开发。 你的提交历史如图所示:

Git rebase和merge区别详解,GIT,git,github,前端

然后,某人又向中央服务器提交了一些修改,其中还包括一次合并。 你抓取了这些在远程分支上的修改,并将其合并到你本地的开发分支,然后你的提交历史就会变成这样:

Git rebase和merge区别详解,GIT,git,github,前端

接下来,这个人又决定把合并操作回滚,改用变基;继而又用 git push --force 命令覆盖了服务器上的提交历史。 之后你从服务器抓取更新,会发现多出来一些新的提交。

Git rebase和merge区别详解,GIT,git,github,前端

结果就是你们两人的处境都十分尴尬。 如果你执行 git pull 命令,你将合并来自两条提交历史的内容,生成一个新的合并提交,最终仓库会如图所示:

Git rebase和merge区别详解,GIT,git,github,前端

此时如果你执行 git log 命令,你会发现你将相同的内容又合并了一次,生成了一个新的提交,会出现两个提交的作者、日期、日志居然是一样的,这会令人感到混乱。 此外,如果你将这一堆又推送到服务器上,你实际上是将那些已经被变基抛弃的提交又找了回来,这会令人感到更加混乱。 很明显对方并不想在提交历史中看到 C4 和 C6,因为之前就是他把这两个提交通过变基丢弃的。

用变基解决变基

如果你 真的 遭遇了类似的处境,Git 还有一些高级魔法可以帮到你。 如果团队中的某人强制推送并覆盖了一些你所基于的提交,你需要做的就是检查你做了哪些修改,以及他们覆盖了哪些修改。

实际上,Git 除了对整个提交计算 SHA-1 校验和以外,也对本次提交所引入的修改计算了校验和——即 “patch-id”。

如果你拉取被覆盖过的更新并将你手头的工作基于此进行变基的话,一般情况下 Git 都能成功分辨出哪些是你的修改,并把它们应用到新分支上。

举个例子,如果遇到前面提到的 有人推送了经过变基的提交,并丢弃了你的本地开发所基于的一些提交 那种情境,如果我们不是执行合并,而是执行 git rebase teamone/master, Git 将会:

  • 检查哪些提交是我们的分支上独有的(C2,C3,C4,C6,C7)

  • 检查其中哪些提交不是合并操作的结果(C2,C3,C4)

  • 检查哪些提交在对方覆盖更新时并没有被纳入目标分支(只有 C2 和 C3,因为 C4 其实就是 C4’)

  • 把查到的这些提交应用在 teamone/master 上面

从而我们将得到与 你将相同的内容又合并了一次,生成了一个新的提交 中不同的结果,如图 在一个被变基然后强制推送的分支上再次执行变基 所示。

Git rebase和merge区别详解,GIT,git,github,前端

要想上述方案有效,还需要对方在变基时确保 C4’ 和 C4 是几乎一样的。 否则变基操作将无法识别,并新建另一个类似 C4 的补丁(而这个补丁很可能无法整洁的整合入历史,因为补丁中的修改已经存在于某个地方了)。

在本例中另一种简单的方法是使用 git pull --rebase 命令而不是直接 git pull。 又或者你可以自己手动完成这个过程,先 git fetch,再 git rebase teamone/master

如果你习惯使用 git pull ,同时又希望默认使用选项 --rebase,你可以执行这条语句 git config --global pull.rebase true 来更改 pull.rebase 的默认配置。

如果你只对不会离开你电脑的提交执行变基,那就不会有事。 如果你对已经推送过的提交执行变基,但别人没有基于它的提交,那么也不会有事。 如果你对已经推送至共用仓库的提交上执行变基命令,并因此丢失了一些别人的开发所基于的提交, 那你就有大麻烦了,你的同事也会因此鄙视你。

如果你或你的同事在某些情形下决意要这么做,请一定要通知每个人执行 git pull --rebase 命令,这样尽管不能避免伤痛,但能有所缓解。

变基 vs 合并

至此,你已学习了变基和合并的用法,你一定会想问,到底哪种方式更好。 在回答这个问题之前,让我们退后一步,想讨论一下提交历史到底意味着什么。

有一种观点认为,仓库的提交历史即是 记录实际发生过什么。 它是针对历史的文档,本身就有价值,不能乱改。 从这个角度看来,改变提交历史是一种亵渎,你使用 谎言 掩盖了实际发生过的事情。 如果由合并产生的提交历史是一团糟怎么办? 既然事实就是如此,那么这些痕迹就应该被保留下来,让后人能够查阅。

另一种观点则正好相反,他们认为提交历史是 项目过程中发生的事。 没人会出版一本书的第一版草稿,软件维护手册也是需要反复修订才能方便使用。 持这一观点的人会使用 rebase 及 filter-branch 等工具来编写故事,怎么方便后来的读者就怎么写。

现在,让我们回到之前的问题上来,到底合并还是变基好?希望你能明白,这并没有一个简单的答案。 Git 是一个非常强大的工具,它允许你对提交历史做许多事情,但每个团队、每个项目对此的需求并不相同。 既然你已经分别学习了两者的用法,相信你能够根据实际情况作出明智的选择。

总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。文章来源地址https://www.toymoban.com/news/detail-622007.html

到了这里,关于Git rebase和merge区别详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Idea使用git拉取代码 : (git merge、git rebase)区别

    我们使用pull拉取远程仓库的代码时,通常有两个选项,一个是 merge ,一个是 rebase ,这两个之间有什么区别呢? 这两个选项都是将远程仓库的代码合并到本地仓库的代码,但是在使用上是不同的。 1、使用merge合并远程仓库的代码是按照代码的提交时间进行展示的,也就是说使用m

    2024年02月16日
    浏览(46)
  • Git:Rebase和Merge之间的区别

    merge的原理是找到这两个分支的祖先commit,在两个分支最新的commit进行三方对比合并 例如下图,共同的祖先commit2,master最新commit6,develop最新commit5, merge会基于2,5,6 这三个commit进行对比: commit6和commit2对比,如果文件的哈希值不一样,同时commit5和commit2对比,发现一样,说

    2024年02月11日
    浏览(36)
  • merge和rebase的区别-Git实操

    实操git管理工具,主要演示如何实现新建分支,提交分支,合并分支到主干,删除分支,管理分支功能。并且详细了解部分功能的区别。git安装与基础使用 顾名思义,在git中,分支指的是从主线上分离出来进行另外的操作,既不影响主线,主线又可以继续干它的事,它可用来

    2023年04月26日
    浏览(34)
  • git merge与git rebase详解

    参考:         http://t.csdn.cn/CkVrR         https://blog.csdn.net/weixin_42310154/article/details/119004977 (1)merge  (2)rebase 经验:         一般来说,不推荐使用rebase。         但为了让分支树看起来更简化,个人分枝偶尔也会选用rebase。这样可以线性的看到每一次提交,

    2024年02月16日
    浏览(36)
  • Git分支的合并策略有哪些?Merge和Rebase有什么区别?关于Merge和Rebase的使用建议

    参考:《Git 权威指南》、《Git团队协作》、快手git管理 (1)工作区域 首先来介绍介绍下Git的工作区域,分为 工作区 、 暂存区 和 仓库区 ,每个区域的转换关系如上图所示。 工作区(workspace) :就是我们平时本地存放项目代码的地方; 暂存区(index/stage) :用于临时存放

    2024年02月04日
    浏览(60)
  • 【git merge/rebase】详解合并代码、解决冲突

    目录 1.概述 2.merge 3.rebase 4.merge和rabase的区别 5.解决冲突 在实际开发中,一个项目往往是多个人一起协作的,头天下班前大家把代码交到远端仓库,第二天工作的第一件事情都是从服务器上拉最新的代码,保证代码版本的一致性。在这种团队协作中大家修改到同一份文件是难

    2024年02月08日
    浏览(53)
  • git合并代码命令 分支合并代码 cherry-pick merge rebase区别

    1.cherry-pick 需要注意 暂存未提交的更改 暂存更改: 使用git stash或git stash push命令暂存当前工作目录和暂存区的更改。你可以提供一个消息作为参数,以便更容易地识别stash项: 执行cherry-pick: 现在,你的工作目录是干净的,可以安全地执行cherry-pick操作了。找到你想要cherry

    2024年04月12日
    浏览(46)
  • git fetch, git pull, git merge, git rebase

    背景: 我们发现很多同学习惯性用git pull拉取远端仓库代码, 但是这会带来一个问题,如果有了本地commit再git pull的话,会产生一个merge commit, 这样的merge commit会导致git log分支节点很多,很乱。 首先聊一聊git pull,git merge,git rebase这些常听到的命令吧,初入git的同学一定还

    2024年02月03日
    浏览(55)
  • 0065__git fetch, git pull, git merge, git rebase

    git fetch, git pull, git merge, git rebase_git pull和merge_送你一朵小莲花的博客-CSDN博客

    2024年02月09日
    浏览(56)
  • git rebase和git merge在团队协作开发中的用法

    git rebase 和 git merge 是在日常开发中常用的用于分支合并的命令,也是非常容易误用的两个命令。本文将通过图文的方式去详解二者之间的区别。 git merge git merge 会为本次的合并过程生成一条新的commit,并将该commit添加到目的分支上。通常用于将feature分支的内容向主分支进行

    2024年02月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包