SVN有哪些merge方式
总的来说,SVN 的 merge
主要有以下 五种类型:
1. 同步合并 (Sync Merge) / 追赶合并 (Catch-up Merge)
这是在分支开发过程中最常用的一种合并。
-
目的 :让你的功能分支保持最新,及时获取主干(
trunk
)上的所有更新,避免与主干偏离太远。 -
方向 :
主干 (Trunk) -> 分支 (Branch)
-
常用命令 :
svn merge ^/trunk
-
执行位置 :在 分支 的工作副本中执行。
-
详细解释 :
你在自己的
feature-A
分支上开发,同时其他同事在trunk
上提交了代码。为了避免最后合并回主干时产生巨大的冲突,你需要定期将trunk
的"新成果"同步到你的分支上。SVN 的合并追踪 (svn:mergeinfo
) 会记住你同步到了哪个版本,下次会自动从那个版本开始继续同步。bash# 1. 切换到你的分支工作目录 cd D:\dev\my-project\feature-A # 2. 执行同步合并 svn merge ^/trunk # 3. 解决冲突并提交到你的分支 svn commit -m "Sync with trunk"
2. 重入合并 (Reintegrate Merge)
这是分支开发完成后的最后一步,也是一个非常特殊的合并。
-
目的:将一个功能分支上所有的"净工作成果"一次性、干净地合并回主干。
-
方向 :
分支 (Branch) -> 主干 (Trunk)
-
常用命令 :
svn merge --reintegrate ^/branches/feature-A
-
执行位置 :在 主干 的工作副本中执行。
-
详细解释 :
你的
feature-A
分支开发测试完毕,准备发布。--reintegrate
会智能地计算出这个分支独有的、纯粹的变更(排除了那些从主干同步过来的变更),然后将这些变更应用到主干上。
黄金法则 :执行完reintegrate
合并后,这个分支的使命就结束了,不应该再被使用。bash# 1. (在分支上) 确保分支已完全同步主干,这是前提! # 2. 切换到主干工作目录 cd D:\dev\my-project\trunk # 3. 执行重入合并 svn merge --reintegrate ^/branches/feature-A # 4. 检查无误后,提交到主干 svn commit -m "Reintegrate feature-A into trunk"
3. 拣选合并 (Cherry-pick Merge)
当你只需要某个分支上的特定几次提交,而不是全部分支内容时使用。
-
目的:像摘樱桃一样,精确地"摘取"一个或多个特定版本的变更,应用到当前工作副本。
-
方向 :任意
URL ->
当前工作副本 -
常用命令 :
svn merge -c <版本号> <源URL>
或svn merge -r <N:M> <源URL>
-
执行位置 :在 目标(想应用变更的地方)工作副本中执行。
-
详细解释 :
最常见的场景是 紧急修复 (Hotfix) 。比如,你在
trunk
的r345
版本修复了一个严重 bug,但此时发布出去的是基于release-1.0
分支的代码。你不需要将trunk
的所有新功能都合并到发布分支,只需要r345
这一个修复。bash# 1. 切换到你的发布分支工作目录 cd D:\dev\my-project\release-1.0 # 2. 拣选合并 r345 这一个提交 # -c 345 等同于 -r 344:345 svn merge -c 345 ^/trunk # 3. 检查并提交到发布分支 svn commit -m "Cherry-pick fix from r345 of trunk"
4. 差异合并 (Differential Merge) / 两棵树合并 (Two-Trees Merge)
这是 SVN merge
最底层、最根本的形式,也是最强大的。
-
目的:计算两个任意 URL(可以在不同版本)之间的差异,并将这个差异作为补丁应用到当前工作副本。
-
方向 :
URL1@REV1
和URL2@REV2
之间的差异->
当前工作副本 -
常用命令 :
svn merge <URL1@REV1> <URL2@REV2>
-
执行位置 :在 目标 工作副本中执行。
-
详细解释 :
这种合并方式不关心历史或血缘关系。它就是纯粹的"找不同,然后应用"。这在处理 没有共同祖先的分支合并 时非常有用。比如,你想将一个完全独立的项目
project-B
的代码强行合并到project-A
。bash# 假设 ^/utils/empty 是一个空目录 # 计算"空"和"project-B"的差异,结果就是"添加所有project-B的文件" svn merge ^/utils/empty ^/projects/project-B .
另一个更现代的实现方式是使用
--ignore-ancestry
参数,它的效果类似。
5. 反向合并 (Reverse Merge)
本质上是拣选合并或差异合并的一种特殊用法,目的是撤销一个或多个已经提交的变更。
-
目的:回滚(Revert)某个已经提交的版本。
-
方向:将历史变更"反向"应用到当前工作副本。
-
常用命令 :
svn merge -c -<版本号> <源URL>
或svn merge -r <M:N> <源URL>
(其中 M > N) -
执行位置:在你想撤销变更的分支/主干的工作副本中执行。
-
详细解释 :
你发现
r250
这次提交引入了一个严重的 bug,需要立即撤销。bash# 假设你在 trunk 的工作副本中 # -c -250 的意思是"应用 r250 的反向变更" svn merge -c -250 . # 或者使用版本范围,注意顺序是反的 # svn merge -r 250:249 . # 提交这次"撤销操作" svn commit -m "Revert commit r250 due to bug X"
总结表格
合并类型 | 核心目的 | 方向 | 常用命令 | 关键点 |
---|---|---|---|---|
同步合并 | 让分支保持最新 | Trunk -> Branch |
svn merge ^/trunk |
在分支生命周期中会多次执行 |
重入合并 | 将分支成果合并回主干 | Branch -> Trunk |
svn merge --reintegrate ^/branch |
分支生命周期最后一次操作,之后分支废弃 |
拣选合并 | 应用特定的变更 | 任意URL -> 当前目录 |
svn merge -c <REV> |
常用于紧急修复,只拿需要的变更 |
差异合并 | 计算并应用任意两点间的差异 | URL1 vs URL2 -> 当前目录 |
svn merge <URL1> <URL2> |
最底层原理,可用于合并无关联分支 |
反向合并 | 撤销已提交的变更 | 历史变更 -> 当前目录 |
svn merge -c -<REV> |
用于回滚错误提交 |
理解了这五种目的,你就能在任何场景下选择最合适的 merge
方式了。
注:合并无关联分支时需要--ignore-ancestry
对于Git,又是怎样的呢
总结对比表
SVN 合并类型 | 核心目的 | Git 主要对应功能 | Git 哲学与备注 |
---|---|---|---|
同步合并 | 分支获取主干更新 | git merge main 或 git rebase main |
merge 保留合并痕迹;rebase 创造线性历史,更整洁。 |
重入合并 | 分支合并回主干 | git merge <branch> |
标准做法。可配合 rebase 实现无合并节点的线性历史。 |
拣选合并 | 摘取特定提交 | git cherry-pick <hash> |
功能完全同名,用法一致,是 Git 的标准功能。 |
差异合并 | 合并无关联分支 | git merge --allow-unrelated-histories |
Git 有专门的参数来处理这种特殊情况。 |
反向合并 | 撤销已提交的变更 | git revert <hash> |
revert 是一个专门、安全的撤销命令,它会创建新的提交。 |
也就是说 git 的merge 不需要特别指定reintegrate,另外git提供了更强大的rebase功能