找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2426

积分

0

好友

340

主题
发表于 前天 03:05 | 查看: 9| 回复: 0

实际开发中,我们通常会在独立的功能分支上进行开发,待功能完成后需要将其整合回主分支。这时就会面临一个选择:该使用 git merge 还是 git rebase 来合并分支?这两者有何区别呢?本文将通过一个模拟的团队协作场景,带你直观地理解它们的不同。

场景准备

首先,我们在一个代码托管平台(例如 GitHub)上新建一个名为 rebaseStudy 的仓库,默认会创建 master 分支。将项目克隆到本地后,准备工作就完成了。

GitHub仓库rebaseStudy的初始页面

同学A:在主分支提交

同学A首先在本地 master 分支上工作。执行 git log,可以看到仓库初始化的提交记录。

$ git log
commit 7d1bdd8a5c37cd574ad00b32cc88ebb7c7f87f16a (HEAD -> master, origin/master, origin/HEAD)
Author: shuyuan1992 <42328986+shuyuan1992@users.noreply.github.com>
Date:   Sun Nov 11 10:07:07 2018 +0800

    Initial commit

接着,同学A新增了一个 a.txt 文件并提交。再次查看提交记录,现在有两条了。
本地master分支的两次提交记录

此时,将本地新的提交推送到远程仓库,就能在远程看到两次提交历史。
GitHub仓库显示两次提交

我们将这两次提交简称为 C1(Initial commit)和 C2(A first commit a.txt)。

同学B:创建开发分支

与此同时,同学B需要开发新功能。他从当前最新的 master 分支(即 C2 提交点)检出一个新的 dev 分支,并将其推送到远程。

$ git checkout -b dev
Switched to a new branch 'dev'
$ git push origin dev
...
 * [new branch]      dev -> dev

创建并推送dev分支

查看远程仓库,可以看到多出了一个 dev 分支。
GitHub仓库显示dev分支

此时的分支状态可以用下图表示:
初始分支状态图:master在C2,dev从C2分出

然后,同学B在 dev 分支上专心开发,并完成了三次提交。查看 git log 如下:
dev分支上的三次新提交记录

我们将这三次提交简称为 C3C4C5。此时的分支图变为:
dev分支开发后状态图

关键冲突场景

现实开发中常出现这种情况:当同学B正准备进行第四次提交时,同学A在 master 分支上又完成了一次新的提交(假设为 C6),并推送到了远程。此时,master 分支已经领先于 dev 分支创建时的基点(C2)。

分支状态更新为:
master分支前进到C6后的状态图

现在,同学B开发完毕,需要将 dev 分支的功能合并到 master 分支。他有两种主流选择:git mergegit rebase

方案一:使用 git merge

操作:在 master 分支上执行 git merge dev
合并过程:

  1. Git 会自动找到 masterdev 两个分支的最近共同祖先,即 C2
  2. dev 分支的最新提交 C5master 分支的最新提交 C6 的内容进行合并,如果存在冲突则需要手动解决。这次合并会生成一个新的合并提交,我们称之为 C7
  3. 最终,master 分支会将 C2 之后 devmaster 的所有提交点(C3, C4, C5, C6)按照提交时间顺序合并到一起。

合并后的分支图示如下,可以看到历史记录出现了分叉和汇合,形成非线性的结构:
merge合并后的分支图,产生新节点C7

方案二:使用 git rebase

操作:首先切换到需要变基的分支,即 dev 分支,然后执行 git rebase master
合并过程:

  1. Git 会将 dev 分支(从共同的祖先 C2 之后开始)的每一次提交(C3, C4, C5)暂时“保存”下来。
  2. dev 分支的基点从 C2 更新为 master 分支的最新提交 C6。
  3. 再将刚才保存的提交依次应用到新的基点(C6)之上,形成新的提交 C3'C4'C5'。在这个过程中如果发生冲突,需要即时解决(解决后执行 git add .git rebase --continue)。

完成 rebase 后,dev 分支的历史就变成了基于最新的 master。此时,只需要再切换到 master 分支执行一次快进合并 (git merge dev) 即可。

最终效果如下图所示,整个历史记录呈现为一条直线,非常清晰:
rebase变基后的线性分支图

你会发现,采用 rebase 后,原来 dev 分支上的几次提交(C3,C4,C5)的哈希值(hash)发生了变化(变为C3‘, C4’, C5‘),但提交内容被保留了下来。master 分支没有产生额外的合并提交。

核心区别总结

操作 特点 历史记录 适用场景
git merge 保留完整的提交历史,包括分支的合并点。会生成一个新的合并提交 非线性,能清晰体现分支的合并时间和路线。 希望保留完整历史,特别是公共分支(如主分支)的合并;团队策略强调追溯每一次合并。
git rebase 将当前分支的提交“移植”到目标分支的最新提交之后。重写了提交历史。 线性,仿佛所有工作都是在目标分支上依次进行的。 希望得到干净、线性的提交历史;在本地功能分支整理提交记录,然后再合并到主分支。

重要提示rebase 操作会改变提交的哈希值,这意味着它重写了历史。因此,一个基本原则是:只对你本地、尚未推送至远程仓库的提交进行 rebase 操作。切勿对已经推送到远程、可能与其他人共享的分支执行 rebase,否则会给协作者带来巨大的同步困扰。

选择 merge 还是 rebase,往往取决于团队的工作流规范和偏好。merge 更安全、更完整地记录了项目演进;rebase 则能创造出更简洁、易于追溯的线性历史。理解两者的差异,有助于你更好地进行版本控制和协作开发

如果你对 Git 的更多高级操作或团队协作DevOps实践感兴趣,欢迎在云栈社区与更多开发者交流探讨。




上一篇:Spring Boot集成Elasticsearch实战:从核心概念到复杂搜索功能实现
下一篇:Flask SQLAlchemy ORM数据查询全解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-14 17:09 , Processed in 0.203777 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表