Git merge 的几种不同模式

Git 中的 merge 可以理解为:把另一个分支上的修改合并到当前分支。不同合并模式的区别,是合并后提交历史如何呈现、是否保留分支痕迹,以及是否重写提交记录。

下面以 main 分支和 feature 分支为例,对常见合并方式进行说明。

main: A---B---C

feature: \---D---E

其中,D、E 表示在 feature 分支上完成的两个提交。


1. Fast-forward merge:快进合并

基本含义

Fast-forward merge 是最简单的一类合并。它发生在当前分支从创建 feature 分支之后没有新的提交时,Git 不需要额外创建合并提交,只需要把当前分支指针直接移动到 feature 分支的最新提交。

合并前:

合并后:

常用命令

bash 复制代码
git switch main
git merge feature

如果 Git 判断可以快进,就会自动执行 fast-forward merge。也可以使用下面的命令强制只允许快进合并:

bash 复制代码
git merge --ff-only feature

这条命令的意思是:如果能够快进就合并;如果不能快进,就直接报错,不创建额外的 merge commit。

特点

此时 feature 分支上包含:

A---B---C---D

main 也包含:

A---B---C---D

也就是说,feature 上的内容没有消失,只是 main 也走到了同一个位置。可以理解成:原来 feature 比 main 领先两个提交;FF merge 后,main 追上了 feature;两者现在站在同一个提交点上。

优点是提交历史非常干净,最终看起来是一条直线;缺点是分支开发的痕迹不明显,后续不容易看出某几个提交原本属于同一个功能分支。


2. No-fast-forward merge:非快进合并

基本含义

No-fast-forward merge 表示即使当前场景可以直接快进,也强制创建一个新的合并提交。这个新的提交通常被称为 merge commit,用来记录某个功能分支被合并进主分支。

合并后:

其中,M 就是新增的 merge commit。

常用命令

bash 复制代码
git switch main
git merge --no-ff feature

特点

优点是可以保留分支结构,能够清楚看出 C、D 是作为一个完整功能分支开发后合并进来的;缺点是提交历史中会多出 merge commit,历史线条不如纯直线简洁。

这种方式适合比较正式的功能开发,例如登录模块、支付模块、实验性功能等。因为这些内容本身就是一个相对完整的开发单元,保留分支痕迹反而更利于后续回溯。


3. Three-way merge:三方合并

基本含义

Three-way merge 严格来说不是一个需要单独手动选择的模式,而是 Git 在无法快进合并时自动采用的合并方式。当 main 和 feature 在共同祖先之后各自都有新提交时,Git 不能简单移动分支指针,只能根据三个版本进行合并。

合并前:

合并后:

三方合并中的"三方"分别是:共同祖先 B、当前分支最新提交 C,以及被合并分支最新提交 E。Git 会比较 C 和 E 相对于 B 的变化,然后尝试把两边的修改合在一起。

常用命令

bash 复制代码
git switch main
git merge feature

特点

如果两边修改的内容不冲突,Git 可以自动合并;如果两边修改了同一文件的同一位置,就可能出现 conflict,需要手动解决冲突后再提交。


4. Squash merge:压缩合并

基本含义

Squash merge 会把 feature 分支上的多个提交压缩成一个新的提交,再放到 main 分支上。它不会把 feature 分支上的原始提交 C、D、E 原样带入 main,而是生成一个包含全部修改的新提交 S。

合并前:

合并后:

常用命令

bash 复制代码
git switch main
git merge --squash feature
git commit -m "add feature"

git merge --squash feature 之后,Git 只是把 feature 分支上的改动放入暂存区,并不会自动提交,因此还需要手动执行 git commit。

特点

优点是主分支历史非常简洁,通常可以做到一个功能对应一个提交;缺点是 feature 分支上原来的多个提交记录不会原样进入 main。

这种方式适合 feature 分支提交比较杂乱的情况,例如提交信息中有 fix、debug、try、test 等临时提交。将这些过程性提交压缩成一个清晰提交,可以提高主分支历史的可读性。


5. Rebase merge:变基后合并

基本含义

Rebase 本身不是 git merge 命令的一种参数,但在实际开发和 GitHub Pull Request 中经常与 merge 放在一起讨论。它的核心思想是:把 feature 分支上的提交搬到 main 分支的最新提交后面。

原始状态:

rebase 后:

这里的 D'、E' 不是原来的 D、E,而是 Git 根据新的基础重新生成的提交,因此 rebase 会重写提交历史。

常用命令

bash 复制代码
git switch feature
git fetch origin
git rebase origin/main

完成 rebase 后,如果要把 feature 合并回 main,通常可以执行 fast-forward 合并:

bash 复制代码
git switch main
git merge --ff-only feature

最终主分支历史会变成一条直线:

特点

优点是主分支历史保持线性,看起来非常清楚;缺点是会改写 feature 分支的提交历史。如果该分支已经被多人共享,不建议随意 rebase。

rebase 后 push

如果这个 feature 分支之前没 push 过,

bash 复制代码
git push origin feature

远程 GitHub 上还没有这个 feature 分支,不存在历史冲突。直接push

如果这个 feature 分支之前已经 push 过

原来可能是:

rebase 之后变成:

普通 push 很可能会失败,这时候应该用:

bash 复制代码
git push --force-with-lease origin feature

它的意思是:如果远程 feature 没有被更新过,就允许覆盖;如果别人已经推了新提交,就拒绝覆盖。


6. 几种模式的对比

|-----------------|------------------------------|----------------|----------|----------------------|
| 模式 | 常用命令 | 历史形状 | 是否保留分支痕迹 | 适合场景 |
| Fast-forward | git merge feature | 直线 | 不明显 | main 没有新提交时 |
| No-ff merge | git merge --no-ff feature | 有分叉和合并点 | 保留 | 正式功能分支 |
| Three-way merge | git merge feature | 有 merge commit | 保留 | main 和 feature 都有新提交 |
| Squash merge | git merge --squash feature | 直线 | 不保留原提交 | feature 提交较乱 |
| Rebase + merge | git rebase + merge --ff-only | 直线 | 不保留原分叉 | 追求干净线性历史 |

fast-forward :直接把 main 指针往前挪
--no-ff :保留分支痕迹,生成 merge commit
three-way :两边都改了,Git 找共同祖先合并
squash :把一整个分支压成一个提交
rebase:把自己的提交搬到 main 最新提交后面


7.GitHub Merge

GitHub Pull Request 中常见的三个按钮,通常对应 Merge commit、Squash merge 和 Rebase merge。

情况一:本地合并进 main,然后 push main

bash 复制代码
git switch main
git merge feature
git push origin main

等价于在本地直接做了最终合并。不需要 GitHub PR merge

但团队开发通常是另一种流程:本地只 push feature,然后在 GitHub 点 PR

bash 复制代码
git switch feature
git push origin feature

然后 GitHub 上点:

Squash and merge

或者:

Create merge commit

或:

Rebase and merge

这时最终合并由 GitHub 完成


一般的PR 流程

bash 复制代码
git switch feature
git add .
git commit -m "add login page"
git push origin feature

然后到 GitHub 上创建 PR:feature → main

审核通过后,在 GitHub 上选择:

Merge commit / Squash merge / Rebase merge

实现最终合并。

相关推荐
视觉小萌新2 小时前
关于Vscode配置企业Git
git
zh_xuan2 小时前
使用命令行把安装包上传到github
c++·git·libcurl·c++工程打包
AC赳赳老秦3 小时前
财务报销自动化:用 OpenClaw 自动识别发票信息、填写报销单、校验报销规则,减少手工操作
运维·网络·eclipse·github·visual studio·deepseek·openclaw
无限进步_3 小时前
二叉搜索树完全解析:从概念到实现与应用场景
c语言·开发语言·数据结构·c++·算法·github·visual studio
zhangfeng11334 小时前
适合 5人以内小团队的Git 工作流 + Code Review + 自动化部署方案 FastAdmin +linunx服务器宝塔系统 外包项目 —
服务器·git·自动化·php·代码复审
念一不念二8 小时前
[Git]git仓库管理的使用
git
HZ·湘怡8 小时前
Gitee 手把手
git·gitee