SVN有哪些merge方式
總的來說,SVN 的 merge
主要有以下 五種類型:
1. 同步合并 (Sync Merge) / 追趕合并 (Catch-up Merge)
這是在分支開發過程中最常用的一種合并。
-
目的:讓你的功能分支保持最新,及時獲取主干(
trunk
)上的所有更新,避免與主干偏離太遠。 -
方向:
主干 (Trunk) -> 分支 (Branch)
-
常用命令:
svn merge ^/trunk
-
執行位置:在 分支 的工作副本中執行。
-
詳細解釋:
你在自己的feature-A
分支上開發,同時其他同事在trunk
上提交了代碼。為了避免最后合并回主干時產生巨大的沖突,你需要定期將trunk
的“新成果”同步到你的分支上。SVN 的合并追蹤 (svn:mergeinfo
) 會記住你同步到了哪個版本,下次會自動從那個版本開始繼續同步。# 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
合并后,這個分支的使命就結束了,不應該再被使用。# 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
這一個修復。# 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
。# 假設 ^/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,需要立即撤銷。# 假設你在 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功能