前提:
在最近的项目中, 我碰到这样一个情况: 第一版 App 上线之后, 团队紧接着进行第二版本的开发, 由于团队成员对 Git 使用不熟悉, 所以开发的每一次提交都是往远端 master 分支上提交.
第一版本打包上线之后, 我想让后续的开发中 master 分支保持代码高可用性, 于是在远端建立新的分支 second_version 用于第二版本的开发, 到时候再合并到 master 分支上, 奈何有的团队成员不会提交远程其他分支, 导致 master 被污染 (如下图)
由于团队成员对 Git 的熟练程度不同, 有的使用可视化工具提交, 有的使用命令行 (比如我), 当使用 merge 的时候会出现如上图所示的问题, 点线图错综复杂, 原因是在 merge 时会将本地的提交与拉取的提交融合成新的提交, 也就是如图所示的 Merge remote-tracking branch..., 并且会将所有的提交显示在点线图上, 十分混乱. 但是使用 rebase 的时候, 点线图则会很优雅:
点线图是一条直线. 网上有很多关于 rebase 和 merge 的区别解释, 以下分享的是我自己对 rebase 的观点, 希望可以帮助大家理解.
rebase 原理
首先大家在开发过程中肯定会经常碰到这样的情况: 当你执行 Git push 时出现错误信息:
这是因为跟你当前分支相关联的远端分支上已经有别人提交了新的代码, 或者说你想 push 的 commit 的基点已经变更 (后面会说明什么是基点).
问题引出: 这里涉及到本地分支与远端分支关联的问题, 使用 Git branch -vv 查看关联关系:
本地 master 默认与 origin/master 相关联, 当你执行 Git push 或
Git push origin master
时, 其完整命令是
Git push origin master:master
, 前一个 master 是你本地的 master, 后一个 master 是远端 master. 所以如果没有特别指定, 无论你在本地的哪个分支, Git push 命令都只会将你本地 master 分支上的代码进行提交. 当你在本地新建其他分支
Git checkout -b test
, 默认是不会与远程分支相关联的. 所以当你在该分支上进行 Git push 时会有如下问题出现
根据提示, 使用
Git push --set-upstream origin test
可以与远端分支 test 进行关联, 这里的 test 要换成自己的分支名.
回到正题
rebase, 故名思意 re-base, 重新定义基点, 当你的代码 push 不上去的时候, 你可以使用 Git pull -r 或是 Git pull --rebase 拉取并合并远端分支, 然后执行 Git status 查看是否出现冲突, 以下是冲突情况:
红框字的翻译大致是: 以'1f618a1'为基点重新定义分支 master.1f618a1 可以看作是每一次提交的唯一标识码.
我将以下图来讲述 rebase 的原理:
不同的字母分别代表不同的提交, 图中从左到右分别以时间从小到大进行排列. 每个 commit 都以前一个 commit 作为基点进行开发, 例如 D 是以 C 为基点进行开发. 当我开发完 D 后, 准备 push 到远端 master 时, Git 会进行检查: 远端 master 的最新节点是否是节点 D 的基点, 即检查远端 master 的基点是否是节点 C, 如果是, 则可以直接 push, 如果不是, 也就是上图的情况: 在你 push 之前远端 master 已经被他人提交了 E 和 F 节点, 这时可以执行 Git pull -r
Git 会以 F 节点作为新的基点, 与 D 节点的代码进行融合, 如果此时出现冲突, 那么你就会被移到临时解冲突的分支, 需要人工解冲突, 解完后执行 Git add -A 保存操作, 再执行 Git rebase --continue 继续后续操作, 你可能会遗漏某一处冲突, 这个完全不同担心, Git rebase --continue 会帮你检查是否解决完成, 如果没有完成则不会让你回到正常分支.
下图是冲突解决完且顺利执行 Git rebase --continue 的情况:
可以看到, 此时我再执行 Git push, 就可以顺利将 D 节点提交到远端 master 上去了:
可以看到, 远端 master 保持了一条直线, 让人看起来非常舒服, 这就是 rebase 的好处, 而不像文章开头使用 merge 那样杂乱, 让人迷惑.
来源: https://www.cnblogs.com/tian874540961/p/12172900.html