Subversion

1,596 views

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,596
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
20
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Subversion

  1. 1. 自由、开源的版本管理系统 南京大学软件学院 2009
  2. 2. <ul><li>1 Subversion 简介 </li></ul><ul><li>2 版本控制的基本原理 </li></ul><ul><li>3 Subversion 基础 </li></ul><ul><li>4 Subversion 基本工作流程及基本操作 </li></ul><ul><ul><li>CheckOut , Commit , Update , Status </li></ul></ul><ul><li>5 Subversion 高级操作 </li></ul><ul><ul><li>Branch/Tag , Merge </li></ul></ul><ul><li>6 Subversion 其他操作(演示) </li></ul><ul><li>7 常见 Subversion 的 GUI 客户端使用(演示) </li></ul>内容简介
  3. 3. 1 Subversion 简介 <ul><li>Subversion 的作用 </li></ul><ul><li>Subversion 的历史 </li></ul><ul><li>Subversion 的特性 </li></ul><ul><li>Subversion 的架构 </li></ul>
  4. 4. Subversion 的作用 <ul><li>一个自由,开源的版本控制系统 </li></ul><ul><li>一个通用系统,不是简单的一个 SCM 系统 </li></ul><ul><li>以替代 CVS 为目标 </li></ul><ul><li>可以管理任何类型文件,并且追踪变更 </li></ul><ul><li>不具有某些和开发紧密结合的特性,如支持某种特定的编程语言,集成构建工具等 </li></ul><ul><li>应用:版本管理,网络硬盘?? </li></ul><ul><li>网址: http://subversion.tigris.org </li></ul>
  5. 5. Subversion 的历史 <ul><li>2000 年, CollabNet 公司开始寻找 CVS 的替代产品 </li></ul><ul><li>2 月,这个公司联系了 Open Source Development with CVS 的作者 Karl Fogel ,他同意为这个项目工作。同时,他还联系了其他几个人一起开发这个新系统 </li></ul><ul><li>3 月, Subversion 开始详细设计和编码 </li></ul><ul><li>2001 年 8 月 31 日, Subversion 第一个完整版本问世 </li></ul><ul><li>经过 1.0 , 1.1 , 1.2 直到现在的 1.4.3 版 </li></ul>
  6. 6. Subversion 的特性(和 CVS 比较) <ul><li>和 CVS 的相似性 </li></ul><ul><li>目录的版本化 </li></ul><ul><li>更加好的文件版本管理(例如对文件拷贝,重命名的处理) </li></ul><ul><li>提交的原子性 </li></ul><ul><li>元数据的版本化 </li></ul><ul><li>可选的网络层 </li></ul><ul><li>对文本文件和二进制文件一致的差异比较算法 </li></ul><ul><li>高效的分支( branch )和标签( tag )操作 </li></ul><ul><li>良好的可维护性 </li></ul>
  7. 7. Subversion 的架构
  8. 8. 2 版本控制的基本原理 <ul><li>客户 / 服务器架构的版本控制简述 </li></ul><ul><li>版本控制的数据共享模型 </li></ul><ul><ul><li>数据共享的问题 </li></ul></ul><ul><ul><li>锁定 - 修改 - 解锁方案 </li></ul></ul><ul><ul><li>拷贝 - 修改 - 合并方案 </li></ul></ul><ul><ul><li>冲突及解决 </li></ul></ul><ul><ul><li>两种方案的对比及选择 </li></ul></ul><ul><li>Subversion 的实现 </li></ul>
  9. 9. 客户 / 服务器架构的版本控制 <ul><li>版本库( Repository ):按照一定格式存储了所有数据,包括文件和目录 </li></ul><ul><li>经过授权的客户端可以连接到版本库,读写库中的文件 </li></ul><ul><li>版本库和普通文件服务器的不同:版本库会记录每一次的更改,所以,客户端可以任意查询更改的历史。例如: ApplicationContext.java 的 1451 版和 1450 版相比修改了什么?谁作的修改?什么时候作的修改?等等 </li></ul>
  10. 10. 版本控制数据共享模型 <ul><li>版本控制系统的核心任务:协作编辑和数据共享 </li></ul><ul><li>基础问题:怎样允许用户共享信息,并且不会因意外而互相干扰? </li></ul><ul><li>数据共享问题的产生 </li></ul><ul><li>解决办法 </li></ul>
  11. 11. 数据共享问题
  12. 12. 解决方案 1—— 锁定 - 解锁方案
  13. 13. 锁定 - 解锁方案的问题 <ul><li>可能导致管理问题,如长期锁定文件不放 </li></ul><ul><li>会导致不必要的顺序开发 </li></ul><ul><li>可能导致死锁 </li></ul><ul><ul><li>例如 Sally 和 Harry 都需要修改 plugin_mgr.c 和 plugin_mgr.h ,两者互相关联, Sally 锁定了 .c 文件而 Harry 锁定了头文件,就会进入死锁状态 </li></ul></ul>
  14. 14. 解决方案 2—— 拷贝 - 修改 - 合并方案
  15. 15. (续图……)
  16. 16. 冲突( Conflict )及解决( Resolve ) <ul><li>冲突的产生:冲突是随着拷贝 - 修改 - 合并方案的产生而带来的问题。两个开发者使用拷贝 - 修改 - 合并方案编辑同一个文件,并且两人的修改发生了交叠时就发生了冲突 </li></ul><ul><li>冲突的解决:当冲突发生时,开发者会看到一对冲突的修改结果,通常情况下,必须让引起冲突的两个人商议之后,手动选择保留一组更改。在这里,版本控制系统只能提示冲突的发生而无法给出解决建议 </li></ul><ul><li>冲突的预防:增加开发者的交流可以最大限度减少冲突的发生,但是不可能杜绝冲突 </li></ul><ul><li>后面可以看到冲突的具体例子以及解决办法 </li></ul>
  17. 17. 两种方案的对比及选择 <ul><li>虽然锁定 - 解锁方案有很多的弊端,但在一些情况下仍然是必须的;虽然拷贝 - 修改 - 合并模型能解决大多数问题,但它也不是万能的 </li></ul><ul><li>比较:文本文件和二进制文件的特点 </li></ul><ul><li>选择:拷贝 - 合并模型假定文件是可以通过上下文合并的。通常情况下,文本文件(例如源代码以及用纯文本, HTML , TeX 等格式保存的文档)因为其内部结构直观可知,容易理解上下文,所以用拷贝—合并方案较好。而二进制文件(例如用 Microsoft Word 格式, PDF 等格式保存的文档及图片,声音,可执行文件,库等)内部结构复杂,且不容易理解更改处的上下文,采用锁定 - 解锁方案较好 </li></ul>
  18. 18. Subversion 的实现 <ul><li>Subversion 主要采用拷贝 - 修改 - 合并模型,配合锁定 - 解锁模型管理数据的共享 </li></ul>
  19. 19. 3 Subversion 基础 <ul><li>基本概念 </li></ul><ul><ul><li>工作拷贝( Working Copy ) </li></ul></ul><ul><ul><li>修订版本( Revision ) </li></ul></ul><ul><li>文件状态 </li></ul><ul><li>混合修订版本的工作拷贝 </li></ul>
  20. 20. 工作拷贝( Working Copy ) <ul><li>工作拷贝是本地机器的一个普通的目录。这个目录的内容是版本库中某个目录的拷贝。工作拷贝是私有工作区,可以任意编辑里面的文件并且发布更改 </li></ul><ul><li>通常,一个工作拷贝对应于版本库的一个子目录,日常的开发是针对工作拷贝进行的 </li></ul><ul><li>工作拷贝里面还有一些由 Subversion 创建和维护的额外文件,用于命令的协助执行,所以它们又叫工作拷贝管理目录。通常,它们都保存在工作拷贝目录及子目录下的 .svn 目录(隐藏)中,凭借这个目录中保存的信息, Subversion 可以识别哪一个文件被修改了,哪一个文件已经过时了,等等 </li></ul>
  21. 21. 修订版本( Revision ) <ul><li>SVN 的提交( Commit )操作是把工作拷贝的更改发布到版本库的一个原子操作。每当一次提交完成后,版本库的文件系统就进入了一个新的状态,叫做一次修订( Revision ),每一次修订都会赋予一个独一无二的版本号,一般是从 0 开始的递增自然数,一个比一个大 </li></ul><ul><li>初始修订版本是 0 ,这只是一个空目录,没有任何内容。随着每次的提交,版本库里仿佛就多了一个当前内容的“快照”。在版本库中,最新的一个修订版本称为 HEAD </li></ul>
  22. 22. 修订版本(图示) (HEAD)
  23. 23. 文件状态 <ul><li>对于工作拷贝的每一个文件, SVN 在管理目录( .svn) 记录两项关键的信息 </li></ul><ul><ul><li>该文件作为基准的修订版本(叫做文件的工作修订版本) </li></ul></ul><ul><ul><li>该文件最后更新的时间戳 </li></ul></ul><ul><li>根据以上两项关键信息,通过和版本库通讯, SVN 可以得到工作拷贝中一个文件的状态,它有下面几种可能 </li></ul><ul><ul><li>未修改,并且版本库也未修改( Up-to-date 状态 ) </li></ul></ul><ul><ul><li>已修改,但是版本库没有修改( Modified 状态) </li></ul></ul><ul><ul><li>未修改,但是版本库已经修改 </li></ul></ul><ul><ul><li>已修改,并且版本库也已修改(需要合并) </li></ul></ul><ul><li>可以用 svn status 命令查看文件状态 </li></ul>
  24. 24. 混合修订版本的工作拷贝 <ul><li>很灵活,但是比较难理解的一个特性 </li></ul><ul><li>混合修订版的工作拷贝:为了灵活,允许一个工作拷贝中存在多个修订版本的文件 </li></ul><ul><li>SVN 特性:修订版本号的全局性。如果某文件的修订号为 N ,并不意味这这个文件被提交了 N 次(甚至有可能这个文件只修改过 1 次),而意味着整个版本库被提交了 N 次 </li></ul><ul><li>当一次 Checkout 或者(整个工作拷贝的) Update 操作完成后,工作拷贝中所有文件都会被更新到同一个版本号 </li></ul><ul><li>两个操作可能引起混合版本的情况:提交和部分更新 </li></ul>
  25. 25. 混合修订版本的工作拷贝(续) <ul><li>提交会引起混合修订版本的情况 </li></ul><ul><li>SVN 的原则:一个 PUSH 的动作不会导致被 PUSH ,或者反之。换句话说,提交某个修改的过程不会导致工作拷贝被修改。在 SVN 中, 更新和提交是分开的 </li></ul><ul><li>当提交修改时,被提交修改的文件版本号将递增,但是工作拷贝中的其他文件仍然保持原有版本号,于是就形成了混合修订版本的格局 </li></ul>
  26. 26. 混合修订版本的工作拷贝(续) <ul><li>很显然,(部分)更新也可能会引起这种情况 </li></ul><ul><li>部分更新是指对工作拷贝中某个文件或者子目录的更新操作(不限于更新到 HEAD ) </li></ul><ul><li>很灵活的一个特性 </li></ul>
  27. 27. 混合修订版本的工作拷贝(续) <ul><li>混合修订版本是一种正常的情况 </li></ul><ul><li>同时,混合修订版本很有用 </li></ul><ul><ul><li>例如,可以用来追溯 Bug 的源头,或者确定某个特性在某个历史版本中是否具有 </li></ul></ul><ul><li>会影响某些命令,如 Log </li></ul><ul><ul><li>例如,当前 HEAD 版本号为 2007 ,而你由于做了很多提交操作,但一直没有做更新操作,导致虽然最新的文件版本号已经是 2007 ,但是仍然有文件版本号只有 1937 ,当你对这个文件用 log 命令想查看历史记录,会发现这个文件的历史到 1937 就为止了 </li></ul></ul><ul><li>混合版本有限制:不是最新的不能提交(喜新厌旧?) </li></ul>
  28. 28. 4 Subversion 基本工作流程和基本操作 <ul><li>Subversion 的基本工作流程是: </li></ul>
  29. 29. (续) <ul><li>基本命令 </li></ul><ul><ul><li>CheckOut </li></ul></ul><ul><ul><li>Update </li></ul></ul><ul><ul><li>Status/Log </li></ul></ul><ul><ul><li>Commit </li></ul></ul><ul><li>SVN 的帮助,用 svn help 命令名称可以得到命令的帮助,或者查看 man 手册和 info 页。 Windows 环境下可以查看 Subversion 带的 CHM 格式参考资料,一般 help 命令就足够了 </li></ul>
  30. 30. CheckOut 操作 <ul><li>从版本库中取出某个目录的拷贝到本机上某个目录的操作叫做 CheckOut ,这个操作是工作的基础 </li></ul><ul><li>语法: checkout(co) URL[@REV]... [PATH] </li></ul><ul><ul><li>注:省略 svn ,即完整的命令应该是 svn checkout … </li></ul></ul><ul><ul><li>例 1 : svn co svn://218.94.9.38/svnrepos/skizcorp/trunk 在当前目录建立一个 trunk 目录,里面是工作拷贝 </li></ul></ul><ul><ul><li>例 2 : svn co svn://localhost/torm I:PROJECTS orm 会在 I:PROJECTS 目录下创建 torm 目录,里面存放工作拷贝 </li></ul></ul><ul><ul><li>例 2 的命令较为常用,因为大多数情况下,我们并不想把工作拷贝目录命名为 trunk </li></ul></ul>
  31. 31. CheckOut 操作(续) <ul><li>指明 Checkout 的版本号 </li></ul><ul><ul><li>默认 CheckOut 操作是针对 HEAD 版本进行的,大多数情况下我们需要 HEAD 版本,但如果需要历史版本,可以用 -r(--revision) 参数或者是用“ @ 版本号 ”的形式 </li></ul></ul><ul><ul><li>例:… -r 1452 会检出 1452 版,如果存在的话 … -r {“2007-05-05”} 会检出最接近这个日期的 版本 … /trunk@1452 效果同第 1 个例子 </li></ul></ul><ul><li>递归与不递归 </li></ul><ul><ul><li>-N :不递归(仅针对顶层目录),否则目录递归(默认,常用) </li></ul></ul><ul><li>注:上面两个参数 -r –N 在很多命令里面都用到 </li></ul>
  32. 32. Update 操作 <ul><li>把版本库的修改同步到本地的过程是 Update </li></ul><ul><li>语法: update(up) [PATH...] </li></ul><ul><ul><li>例 1 : up 直接把工作拷贝更新到最新版( HEAD 版) </li></ul></ul><ul><ul><li>例 2 : up -r 2007 更新到 2007 版 </li></ul></ul><ul><ul><li>例 3 : up doc/design 只更新 doc/design 下的文件 </li></ul></ul><ul><li>-r 和 -N 参数仍然有用 </li></ul><ul><li>Update 会修改被更新目录的 BASE 版本号 </li></ul>
  33. 33. 文件状态 <ul><li>BASE 版:某个文件的 BASE 版本是指存放在管理目录 .svn 中的该文件拷贝的版本, Revert 会使该文件回到 BASE 版本 </li></ul><ul><li>做 Update 操作时, SVN 会打印出受影响文件的状态,有以下几种: </li></ul><ul><ul><li>A Added </li></ul></ul><ul><ul><li>D Deleted </li></ul></ul><ul><ul><li>U Updated </li></ul></ul><ul><ul><li>C Conflict </li></ul></ul><ul><ul><li>G Merged </li></ul></ul><ul><li>若提示 C ,表示冲突,冲突可以用 status 命令加 -u 参数来预测 </li></ul>
  34. 34. Revert 操作——时光倒流 <ul><li>所谓 Revert ,是指放弃对某个文件的修改,把该文件的内容回复和 BASE 版本相同,也就是,把该文件的状态回复到未修改状态 </li></ul><ul><li>语法: revert 文件 / 路径 </li></ul><ul><li>例子 </li></ul><ul><ul><li>例 1 revert abc.c 丢弃对 abc.c 的所有修改 </li></ul></ul><ul><ul><li>例 2 revert src/edu/nju/pojo 放弃对此目录下所有文件的修改 </li></ul></ul>
  35. 35. 冲突解决 <ul><li>当文件发生冲突时, SVN 会额外创建 3 个不受版本控制的文件,同时被冲突文件如果能够合并,会在被冲突文件内部留下冲突记录。例如,冲突的文件为 plugin.c , BASE 版本是 1458 , HEAD 为 1459 ,会产生 3 个临时文件 plugin.c.mine , plugin.c.r1458 , plugin.c.r1459 , </li></ul><ul><li>解决思路: A. 手动修改被冲突文件 B. 放弃自己的更改 </li></ul><ul><li>实际中,解决办法很灵活,一般需要与他人商量 </li></ul><ul><li>注意:由于这 3 个文件是在 Update 后才创建的,而 Update 之后,工作拷贝的 BASE 目录已经变成更新后的版本了,所以放弃自己的更改会回到新版本 </li></ul><ul><li>如果不是用 Revert 的方法解决冲突的话,由于那 3 个临时文件留在那里,会使 Subversion 认为冲突没有解决,所以要运行 resolved 命令告诉 SVN 冲突解决或者删除临时文件 </li></ul>
  36. 36. 工作拷贝中对文件的操作 <ul><li>编辑文件,没什么好说的 </li></ul><ul><li>把一个文件加入 SVN 版本控制,用 add 命令 </li></ul><ul><li>从版本控制中移除,用 delete ( rm, remove )命令 </li></ul><ul><li>移动或者重命名,用 move(rename) 命令 </li></ul><ul><li>拷贝,用 copy 命令 </li></ul><ul><li>创建目录,用 mkdir 命令 </li></ul><ul><li>具体命令用法请参照文档 </li></ul><ul><li>注意:尽量不要用操作系统提供的命令管理文件,这样 Subversion 不知道更改 </li></ul>
  37. 37. 检验修改 <ul><li>通过 status 命令可以检查工作拷贝的状态 </li></ul><ul><li>通过 diff 命令可以检查更改的内容 </li></ul><ul><li>参考 SVN 手册 </li></ul><ul><li>注意: SVN 对文件属性的更改和文件内容的更改是分开管理的 </li></ul>
  38. 38. 提交修改 <ul><li>一般在提交修改之前,必须运行一下 update 操作来合并别人作出的新更改。 </li></ul><ul><li>提交用 commit 命令 </li></ul><ul><li>--message 参数:说明本次提交的有关信息,如为什么要作出这个修改等等。 </li></ul><ul><li>参考 SVN book </li></ul>
  39. 39. 5 Subversion 高级操作 <ul><li>SVN 的高级操作主要包括分支( Branch/Tag )以及合并( Merge )操作 </li></ul><ul><li>分支操作 </li></ul><ul><li>切换 URL </li></ul><ul><li>合并操作 </li></ul>
  40. 40. 为什么需要分支? <ul><li>你在开发一个软件,基于 Windows 平台。有一天,老板找到你,希望你把这个软件移植到 Linux 平台下,同时又不放弃原有版本,怎么管理代码? </li></ul><ul><li>你的产品即将发布,需要进行一段时间的 Alpha , Beta 测试直至正式版 Release 。同时,市场的竞争迫使你必须马不停蹄的开发下一个新版本,增加许多新的特性。两个工作必须同时进行,怎么管理代码? </li></ul>
  41. 41. 什么是分支?
  42. 42. 分支的概念 <ul><li>从图中可以看到,分支是开发的一条“支线”。它独立于其他开发的线路,并且和其他线路并行开发 </li></ul><ul><li>但是,所有的分支都有共同的历史,有着原先共同的主线 </li></ul>
  43. 43. 创建分支 <ul><li>创建分支使用 copy 命令 </li></ul><ul><li>语法: copy 源目录 目标目录 </li></ul><ul><li>方法 </li></ul><ul><ul><li>方法 1 :先把目录 checkout 到本地,在本地执行 copy 命令后提交至版本库 例: svn co svn://localhost/ svn copy trunk/ branches/mybranch svn commit –m “My branch created” </li></ul></ul><ul><ul><li>方法 2 :直接用 copy 命令对版本库中两个 URL 进行操作 例: svn copy svn://localhost/trunk svn://localhost/branches/mybranch –m “My branch” </li></ul></ul>
  44. 44. 创建分支前后版本库的变化 <ul><li>之前 之后 </li></ul>
  45. 45. 在分支上工作 <ul><li>要想在分支上工作,需要一个对应于分支的工作拷贝。有两种方法可以获得这种工作拷贝 </li></ul><ul><ul><li>方法 1 :直接从分支的 URL 上 Checkout 出工作拷贝(适用于没有工作拷贝的情况) </li></ul></ul><ul><ul><li>方法 2 :使用 switch 命令切换工作拷贝对应的 URL (在有工作拷贝的基础上) </li></ul></ul>
  46. 46. Switch 操作 <ul><li>Switch 操作可以使工作拷贝在不同的分支之间或者在 位于不同服务器上 相同的 版本库 的 分支间切换。它的作用是改变工作拷贝对应的 URL </li></ul><ul><li>Switch & Update : Update 命令是 Switch 命令的一个子集 </li></ul><ul><li>语法: switch [--relocate] 目标 URL </li></ul><ul><li>慎用 -relocate 选项 </li></ul>
  47. 47. 分支的合并( 1 ) <ul><li>分支的合并是指把修改从分支拷贝到主干或者把主干的修改拷贝到分支的过程。 </li></ul><ul><li>传统方法: diff + patch </li></ul><ul><ul><li>例子: svn diff –r 2000:2007 svn://localhost/trunk > patchfile patch –p0 < patchfile 这个例子取出主干 2000 版到 2007 版的修改,然后把它应用到工作拷贝(工作拷贝这个时候一般对应于某个分支) </li></ul></ul><ul><li>只适用于文件内容,对于目录树结构无能为力 </li></ul>
  48. 48. 分支的合并( 2 )—— Merge 操作 <ul><li>Merge 操作和传统方法十分类似,但是它能够处理目录树的修改,而不限于单个文件内容 </li></ul><ul><li>语法: merge 初始版本树 最终版本树 目标 </li></ul><ul><li>常用语法: merge 初始版本 : 最终版本 版本库 URL 目标 </li></ul><ul><li>作用:取出初始版本到最终版本的修改,然后把它应用到当前工作拷贝 </li></ul><ul><li>例子 </li></ul><ul><ul><li>merge svn://localhost/trunk@2000 svn://localhost/trunk@2007 my_wc </li></ul></ul><ul><ul><li>merge –r 2000:2007 svn://localhost/trunk my_wc </li></ul></ul>
  49. 49. SVN 版本库常用目录组织结构
  50. 50. 6 Subversion 其他操作及命令行客户端演示 <ul><li>log , list , import , cleanup , info 等命令 </li></ul><ul><li>参考 SVN Book </li></ul>
  51. 51. 7 图形界面客户端的使用及演示 <ul><li>常见的图形界面客户端: Tortoise SVN ( Windows ), Subclipse ( Eclipse 插件, Linux/Windows ) </li></ul><ul><li>观看演示 </li></ul><ul><li>参考各个客户端的文档 </li></ul>

×