SVN分支的合并和同步

来源:互联网 发布:mac microsoft office 编辑:程序博客网 时间:2024/05/18 04:58

1. 概述

先说说什么是 branch

按照 Subversion 的说法 , 一个branch是某个development line (通常是主线也即 trunk) 的一个拷贝 , 见下图 :

branch

branch 存在的意义在于 , 在不干扰 trunk 的情况下 , 和 trunk 并行开发 , 待开发结束后合并回 trunk 中 , 在 branch 和 trunk 各自开发的过程中 , 他们都可以不断地提交自己的修改 , 从而使得每次修改在repository中都有记录 ;

设想以下场景 , 如果你的项目需要开发一个新功能 , 而该功能可能会修改项目中的绝大多数文件 , 而与此同时 , 你的另一位同事正在进行 bug fix , 如果你的新功能不在 branch 中开发而直接在 trunk 中开发 , 那么你极有可能影响另一位同事的bug fix , 他在 bug 修复中可能会遇到各种各样的问题 , 因为你的频繁提交代码引入了过多的不稳定因素 ; 你可能会说 , 那我在开发的过程中不提交不就行了 , 等到我全部开发结束我再提交 , 是 , 你可以这么做 , 那还要版本控制干什么呢 ? 也许等到你最后提交代码的时候 (也许一周 , 也许两周 ? ) , 你会发现有一大堆 conflict 等着你 resolve…

那么 , 正确的做法是什么 ? 使用 branch , 从 trunk 创建 branch , 然后在你的 branch上开发 , 开发完成后再合并到trunk中 ;

下面说说什么叫做合并

很好理解 , 当 branch 开发完成后 (包括必要的测试) , 将 branch 中的修改同步到 trunk 中 , 这个过程有可能包括修改文件 , 增加文件 , 删除文件等等 ;

说到这里 , 貌似本文差不多可以结束了 , 不就是分支和合并么 ? 只要再简单地说说如何建立分支和如何合并就可以收尾了 , 可能只需两个命令 , 也可能只需鼠标点几下然后键盘敲两下即可 ; 其实事情远非这么简单 , 爱动脑筋的同学可能会问了 , 将 branch 的改动 merge 到 trunk 的时候 , 和上文说的直接在 trunk 中全部开发完然后提交有何区别 ? 你最后还不是要处理一大堆conflict ?

这个问题问得非常好 , 其实这正是本文的重点 : branch 和 trunk 在并行开发的过程中如何感知对方 , branch 如何才能在开发过程中不会和 trunk 越走越远 , 导致最后无法合并 ? 试想一下 , 如果在你开发 branch 的过程中 , trunk中 的某个类文件已经被删除了 (这可能是另外一个家伙在另一个 branch 上开发了两周后才合并到 trunk 的) , 而你竟然在这个类文件上做了大量修改 , 试问你到最后合并回 trunk 的时候该有多蛋疼 ? 解决这一问题的唯一手段是 , branch 要不停地和 trunk 保持同步 , 你要及时地知道 trunk 都做了什么修改 , 这些修改是否会影响你正在开发的新功能 , 如果需要 , 你必须及时调整 branch 的代码 , 使之能与 trunk “兼容” ;

那么如何让 branch 和 trunk 保持同步 ?
合并 , 从 trunk 合并到 branch , 你没听错 , 是从 trunk 合并到 branch ; 关于 TortoiseSVN 的合并 , 有几点需要注意 :

  • TortoiseSVN 的合并发生在本地 , 也即你的 working copy 中 , 你无需过多担心会对 repository 中的代码造成影响
  • 不管是从 trunk 合并到 branch 还是最终从 branch 合并回 trunk , 在每次合并前最好先 update , 然后将本地的修改先全部 commit , 保护好现场 , 万一合并不理想随时都可以 revert
  • 合并完成后看是否能正确编译 , 然后测试验证 , 最后将合并后的改动提交到repository


2. 实例操作

下面我将一步步的演示如何一次完整的 branching 和 merging , 包括创建分支 , 分支开发 , 分支和主线同步 , 分支合并到主线的全过程 , 甚至包括如何在本地创建一个测试用的 repository ;

1. 本地Repository的创建

repository 的创建很简单 , 假设我要在 D:\TortoiseSVN\TestRepository 目录中创建 repository , 只需右键 TestRepository 目录 , 依次选择 “TortoiseSVN” -> “Create repository here” 便完成了 repository 的创建 ;

2. Checkout

假设要 Checkout 到 D:\TortoiseSVN\TestSVN , 同样很简单 , 在 D:\TortoiseSVN 目录下创建 TestSVN 目录 , 然后在该目录上右键 , 选择 “SVN Check out…” , 在弹出的窗口中的 “URL of repository” 中填入”file:///D:/TortoiseSVN/TestRepository” , 其他默认即可 , 最后点击ok ;

3. trunk 创建新项目 MyProject

相当简单就不赘述了 , 只列出本次操作所作出的修改 :

my_project

4. 创建 branch

/trunk/MyProject 目录上右键 , 依次选择 “TortoiseSVN” -> “Branch/tag…” , 在弹出窗口的 “To URL” 中填入分支的地址 , 在这里目标 revision 选择 HEAD revision , 如下图所示,添加 log 后点击 ok 分支便建立了 ; 这个操作速度非常快 , 新建的 branch 在 repository 中其实只是一个指向 trunk 某个 revision 的软连接而已 , 并没有真的复制文件 ;

create_branch

5. Checkout 分支

右键 TestSVN 目录选择 “TortoiseSVN Update” 即可将刚刚建立的分支下载回本地 , 进入 /branches/MyProject 目录下你会发现其文件结构和 /trunk/MyProject 一模一样 ;

* 6. branch 提交一个新文件*

branch_commit

7. trunk 紧接着提交一个修改

trunk_alter

8. branch 再次提交一个修改

branch_alter

9. 将 trunk 中的修改同步到 branch

6-8 演示的是 branch 和 trunk 在独立/并行地开发 ; 为了防止在 “错误” 的道路上越走越远 , 现在 branch 意识到是时候和 trunk 来一次同步了 (将 trunk 合并到 branch) ;

首先 , 在本地 trunk 中先 update 一下 , 有冲突的解决冲突 , 保证 trunk 和 repository 已经完全同步 , 然后在本地 /branches/MyProject 上右键 , 依次选择 TortoiseSVN -> Merge.. , 在弹出的窗口中选择第一项 Merge a range of revision , 这个类型的 Merge 已经介绍得很清楚 , 适用于将某个分支或主线上提交的多个 revision 间的变化合并到另外一个分支上 ;

branch_merge

点击 next 后 , 出现如下窗口 :

branch_merge_next

由于是要从 trunk 合并到 branch , 理所当然这里的 URL to merge from 应该填 trunk 的路径 , Revision range to merge 很好理解 , 就是你要将 trunk 的哪些 revision 所对应的变化合并到 branch 中 , 可以是某一连串的 revision , 比如 4-7 , 15-HEAD , 也可以是某个单独的 revision 号 ; 由于在 r4 中 , trunk 修改了 Person.java 中的 talk() 方法 , 所以这里的 revision 只需填 4 即可 ; 点击 next 后出现下图 :

branch_merge_comp

在这里只需保留默认设置即可 ; 在点击 Merge 按钮前你可以先 Test merge 一把 , 看成功与否 , 以及 merge 的详细信息 , 点击 Merge 按钮后 trunk 所做的修改将同步到 branch 中 ;

10. 提交合并后的 branch

merge_branch_commit

至此 , branch 已经完全和 trunk 同步 , branch 和 trunk 的代码相处很融洽 , 没有任何冲突 , 如果 branch 已经开发结束 , 那是时候将 branch 合并回 trunk 了 ; 当然 , 如果 branch 还要继续开发 , 那你将不断地重复 6-10 这几个步骤 ;

11. 将 branch 合并回 trunk

在本地 /trunk/MyProject 上右键 (注意是在主线的目录上右键) , 依次选择 TortoiseSVN -> Merge... , 在弹出的窗口中 , Merge type 选择第二项 Merge two different trees , 可以理解为合并两个树 :

branch_to_trunk

点击 Next 后出现如下窗口 :

branch_to_trunk_next

在 From 和 To 中都选择要合并的分支目录 , 在 From 的 Revision 选择创建分支时的那个 Revision , 具体就是点击 Show log , 选择最下面那一条 , 在 To 的 Revision 选择 HEAD Revision , 也就是最新操作 ;

点击 Next , 下一个页面使用默认项 , 点击Merge :

branch_to_trunk_comp

12. 提交合并后的 trunk

so easy…

13. 删除 branch

如果你认为你新加的功能已经开发完成了 , 你可以删除你的分支 ;


3. 总结

  • branch 主要用于新功能的开发
  • 合并发生在本地 working copy , 只要你不提交就不会影响到 repository
  • 合并前一定要先update/commit , 保证不会 out of day , 并将本地的修改保存到 repository
  • branch 和 trunk 并行开发的过程中 , 要经常同步 , 将 trunk 的修改合并到 branch , 合并时选择 Merge a range of revision
  • branch 最后合并回 trunk时 , merge type 选择 Merge two different trees


4. 常见问题

1. SVN:Previous operation has not finished; run ‘cleanup’ if it was interrupted

安装 SVN 客户端的命令行 , 如下图 :

svn_cmd

Check out 目录下输入 svn cleanup 就可以了 ;

作者 Github : tojohnonly , 博客 : EnskDeCode

原创粉丝点击