如果您还是分不清git中的merge和rebase该如何使用,建议看看这篇文章!
·

Git 中 merge 和 rebase 的区别。它们都是用来整合不同分支的代码变更,但实现方式和最终的提交历史(commit history)有显著不同。
核心区别一句话总结:
merge:创建一个新的“合并提交”(merge commit),将两个分支的历史合并在一起,保留了完整的分支历史。rebase:将一个分支的提交重新应用(replay)到另一个分支的最新提交之上,使历史看起来像是线性发展。
一、 前提:创建示例场景
假设我们有一个项目,主分支是 main。开发新功能时,我们从 main 分出一个新分支 feature。
-
初始状态 (main 分支)
A --- B --- C (main) -
开发新功能 (feature 分支) 你在
feature分支上进行了两次提交:D --- E (feature) / A --- B --- C (main) -
同时,main 分支也有新提交 在你开发
feature时,其他人向main分支推送了一个修复提交F:D --- E (feature) / A --- B --- C --- F (main)
现在,你完成了 feature 分支的开发,需要将你的更改整合到 main 分支中。这时,merge 和 rebase 就派上用场了。
二、 使用 merge
操作:
# 切换到 main 分支
git checkout main
# 将 feature 分支合并进来
git merge feature
结果: Git 会创建一个新的“合并提交”(Merge Commit),通常标记为 M。这个提交有两个父提交:F (main 的最新提交) 和 E (feature 的最新提交)。
D --- E
/ \
A --- B --- C --- F --- M (main)
特点:
- 保留历史:完全保留了
feature分支的存在和开发历史。你可以清晰地看到feature分支是从C点分叉出去的,并在M点合并回来。 - 简单直接:操作简单,不易出错。
- 历史记录真实:反映了实际的开发流程,即两个分支是并行开发的。
- 提交历史可能复杂:如果项目有很多分支频繁合并,提交历史会变成一个“网状结构”,对于只想看主干线性发展的开发者来说,可能显得杂乱。
三、 使用 rebase
操作:
# 切换到 feature 分支
git checkout feature
# 将 feature 分支变基到 main 分支的最新提交上
git rebase main
# 切换回 main 分支
git checkout main
# 将已经变基好的 feature 分支快进合并(fast-forward merge)
git merge feature
详细过程:
-
git rebase main:- Git 会找到
feature和main的共同祖先(这里是C)。 - 它会暂时移除
feature分支上的提交D和E。 - 然后,它将
main分支的最新提交F应用到feature分支。 - 最后,它将之前移除的提交
D和E重新应用到F之后。注意,D和E会变成新的提交(内容相同,但哈希值不同),我们用D'和E'表示。
此时的状态:
A --- B --- C --- F --- D' --- E' (feature) \ (main) - Git 会找到
-
git merge feature: 因为feature现在是main的直接后续,所以这次合并只是一个简单的“快进”(fast-forward),不需要创建合并提交。最终状态:
A --- B --- C --- F --- D' --- E' (main, feature)
特点:
- 线性历史:提交历史看起来非常干净、线性,没有多余的合并提交。
- 历史记录被重写:
D和E被“重写”为D'和E'。虽然内容一样,但它们的提交哈希值、作者时间和父提交都变了。 - 可能丢失上下文:
feature分支曾经存在过的事实被“抹去”了,看起来像是D'和E'是在F之后直接开发的。 - 需要谨慎:永远不要对已经推送到公共仓库的提交进行
rebase。因为这会重写历史,如果你的同事基于旧的D和E进行了工作,会产生严重的冲突。
四、 如何选择?
| 场景 | 推荐操作 | 原因 |
|---|---|---|
合并公共分支(如 develop 合并到 main) | merge | 保留完整的分支历史,清晰地记录了发布周期。 |
| 整合来自其他团队的分支 | merge | 尊重他人的工作流程,保留其分支历史。 |
| 清理本地功能分支,准备合并 | rebase | 在将 feature 分支推送到远程前,用 rebase 更新到最新的 main,然后进行 merge 或 rebase 后的 fast-forward merge。 |
| 希望提交历史干净、线性 | rebase | 适用于个人项目或团队约定使用 rebase 的情况。 |
| 协作开发,分支已共享 | 避免 rebase | 重写已共享的历史会导致协作混乱。 |
五、 总结
merge是“包容”的,它忠实地记录了所有分支的并行开发过程,适合团队协作和保留历史上下文。rebase是“重塑”的,它通过重写提交历史来创造一个看似线性的、更简洁的提交记录,适合在合并前清理自己的本地工作。- 还是不知道该怎么用,那就闭眼睛用
merge,永远不会错!
最佳实践建议:
- 在本地开发功能时,可以频繁使用
git rebase main来保持feature分支与main同步,避免后期合并时出现大量冲突。 - 当功能开发完成,准备合并时,如果团队允许,可以先
rebase再进行fast-forward merge,以保持主分支的线性。 - 如果团队要求保留所有分支历史,则直接使用
merge。
更多推荐



所有评论(0)