1、 SVN 分支与 合并 一、 分支与 合并的概念 二、 SVN 分支 的意义 三、 如何创 建分支与合并分支 一、 分 支与 合并的 概念 : 分支: 版本 控制 系统 的一 个特性 是能 够把 各种 修改 分离出 来放 在开 发品 的一 个分 割线上 。 这 条线 被称为 分支 。 分 支经 常被 用来试 验 新的特 性, 而不 会对开 发 有编 译错误 的干 扰。 当新 的特 性足够 稳定 之后 , 开 发品 的分支 就可 以混合 回主 分支 里 ( 主干线) 。 合并: 分 支用 来维 护独 立的 开 发支 线,在一 些阶 段,你 可能 需要 将分 支上 的修 改 合并到 最新 版本 ,
2、或 者将 最新版 本的 修改 合并 到分 支。 二、 SVN 分支的意义: 简单说 ,分 支就 是用 于区 分开发 版本 与当 前发 布版 本的。 1、 主干 负责 新功 能的 开发 2.、 分 支负 责修 正当 前发 布 版本的 bug (对 于可 以放入 下个 发布 版本 的改 进性 bug 可以 直接 在主 干上 开发 ) 3.、 分支 上修 改的 bug,经 常 性 merge 到主干 上, 尽量及 时 merge ( 避免 大面积 红色区 域)。 4.、 只能 分支 往主 干靠 拢(merge ) ,不 能反 向! 5.、直到 下个 新版 本发 布, 该 分支 停止 修改 三、 如何
3、创建分支与合并 分支 : 1、首 先要 在你 的版 本库 存 里创建 主干 目录 ,通 过版 本库浏 览器 ,如 图 1 所示 : (图 1) 2、输入版本库 URL 地 址,如图 2 所示: (图 2) 3、进入版本库浏览器主目录,如图 3 所示: (图 3) 4、创建主干目录,如图 4 所示: (图 4) 5、主干目录(trunck) ,如图 5 所示:(图 5) 6、把你要加入版本控制的文件加入主干,如图 6-8 所示: (图 6) (图 7) (图 8) 7、从主干里检出文件到你的本地工作副本上,如图 9-10 所示: (图 9) (图 10) 8、选择你要创建分支的工作副本,如图 1
4、1 所示: (图 11 ) 9、在“ 至 URL ” 里填 写版本库中要存放分支的目录, 如图 12-13 所示: (图 12) (图 13) 注 意: 这时候工作副本 对应版本库的路径仍为原来对应的主干的目录。 10、再从分支里检出内容到本地目录上,如图 14-15 所示: (图 14) (图 15) 11 、 打开刚从分支里检出的工作副本目录, 修改里面的 test.txt 文档并提 交,如图 16-17 所示: (图 16) (图 17) 注 意: 这时提交的修改 只会提交到分支上,并不会更改主干上的内容。 12、选择从主干上检出的工作副本,选择合并,如图 18 所示:(图 18) 13
5、、 选择合并类型 (合 并类型在文档的最后有专门的介绍) , 如果 19 所 示: (图 19) 14、 选择合并选项 (合 并选项在文档最后有专门的介绍) ,如 图 20 所示: (图 20) 15、在合并之前,可以先进行测试合并,如图 21 所示: (图 21) 16、测试合并成功后,点击“合并”按钮进行合并,如图 22 所示: (图 22) 17、 合并完成后, 打开 test.txt 文件 , 这时候可以看见文件的内容跟分支 里的内容一样,并且文件上有红色叹号标记(说明已经修改过) ,如图 23 所示: (图 23) 18、在主干上提交修改就完成了合并,如果 24 所示: (图 24)
6、 对 svn 分 支合 并类型 和深 度的 理解 : 合并的工作是把主干或者分支上合并范围内的所有改动列出,并对 比当前工作副本的内容, 由合并者手工修改冲突, 然后提交到服务器的 相应目录里。 如果当前工作副本是主干, 则合并的范围是分支上的改动, 如果工作副本是分支的, 则合并范围是主干上的改动, 并且一定要注意, 合并的起始位置 URL 一定要和当前的工作副本的 URL 是相同的。 一 、合 并一个 范围 的版本 此类型应用最为广泛,主要是把分支中的修改合并到主干上来。在 主干上点击右键选择合并,然后选择合并类型:合并一个范围的版本。 合并的源 URL 填写的 是要合并的分支的 URL
7、, 待合并的版本范围 如果 为空, 则指的是合并分支上所有的版本, 即自从分支创建以来到分支当 前最新版本的所有演变。如果只是选择其中一个版本,或者几个版本, 那么就表示只是将制定的 n 个版本的变化合并到主干上。 如果只是选择 其中一个版本, 那么表示只是选择那个版本的修改, 之前或之后的修改 将不被采纳。 二 、复 兴合并 复兴合并可以理解为是第一种合并类型的一种特例, 在复兴合并中, 主干可以理解为是自从开创分支之后没有任何修改, 而分支是经过修改 的, 而且合并中分支是没有版本选择的。 经过复兴合并, 分支中所有的 修改都会合并到主干中, 合并的结果将使得分支和主干一模一样, 从而 可
8、以删除分支。 三 、合 并两个 不同 的树 此类型与前两种类型不同,第一种类型可以选择分支合并的版本, 主干不能选择版本;第二种类型是主干和分支都不能选择合并的版本; 而这种类型则是无论是主干还是分支都可以选择合并的版本, 即可以选 择过去的一个主干版本与分支的某个版本进行合并。 合并的时候以选择 的分支版本为主, 如果选择的主干版本与分支版本有不同的地方, 合并 时主干部分将被放弃。 起始 URL :选择主干 目录的 URL (应当和 当前工作副本的 URL 一致, 这个是所谓的合并点) 结束 URL :选择要合 并的分支的 URL 。 起始和结束的版本: 一般起始版本应当找到最后一次同步时
9、的版本, 如 果从没有同步过(第一次合并) ,则选择创建分支时的版本,结束版本 一般是最新版本, 如果你不想将某些内容合并进主干的话, 也可以选择 一个合并点。 实例: 主干 A 在 95 版本的时候创建分支 B ,此时两 棵树都是 95 版本 1、 我在分支 B 上增加 文件 test.txt,提交。此时版本库升级到了 96 版 本; 2、 我在 A 上选择合并类型 1,合并分支最新版本,结果是把 test.txt 加入 A ; 3、 我在 A 上选择合并类型 2,合并分支最新版本,结果同上; 4、 我在 A 上选择合并类型 3,合并分支最新版本,结果同上; 5、 我在 A 上增加文件 te
10、st2.txt ,提交,此时版本库升级到了 97 版本; 6、 我在 A 上选择合并类型 1,合并分支最新版本,结果是把 test.txt 加入 A ; 7、 我在 A 上选择合并类型 2,合并分支最新版本,结果是把 test.txt 加入 A ; 8、 我在 A 上选择合并类型 3,主干选择当前 97 版本,合并分支最新 版本,结果是把 test.txt 加入 A ,把 test2.txt 从 A 删除; 9、 我在 A 上选择合并类型 3,主干 97 以前的版本,合并分支最新版 本,结果是把 test.txt 加入 A ,而 A 中保留着 test2.txt 。 将分支合并到主干上, 首先
11、需要在主干的工作副本下进行, 合并的范围 是从主干的上次合并的版本开始到分支上最新的版本结束, 如果是第一 次合并, 则从主干创建分支的版本开始, 所以每次合并要做好说明, 在 日志中体现, 不然忘记了下次再合并就有点麻烦。 其实, 应当尽量避 免 一个分支合并多次, 分支的作用一般为了解决 bug,一 旦 bug 对应 结束 了, 分支的使命就结束了, 以后再出现其他的问题, 应当重新建立分支, 这样就不会出现多次合并的问题了。 分支的 合并深度 合 并深 度: 一、工作副本:即你当前的工作目录,一般默认为这个选项; 二、 全递归: 即你选择 的目录的版本库, 包括了其下面的子文件, 子文
12、件夹,包括子文件夹里面的内容; 三、直接子节点,包括文件夹:即你选择的目录下面的文件,文件夹, 但是不包括文件夹里面的子文件,子文件夹; 四、 仅文件子节点: 即 你选择的目录下面的文件, 但不包括文件夹, 当 然不包括的文件夹下面的所有内容也都不纳入合并范围; 五、仅此项:没有任何合并内容。 实 例: 1、主干 test 文件夹下面有 text.txt 文件,把 test 文件夹创建分支 test2 2、在 test2 文件夹下面增加 test21 文件夹,在 test21 文件夹下面增加文 件夹 test211 ,在 test211 文件夹下面增加文件 test211.txt ;修改 te
13、st2 文 件夹下面的文件 test.txt ,增加文件 test2.txt 。提交 3、右键 test 文件夹合并 test2 文件夹,选择工作副本。则 test 文件夹中 原先的 test.txt 文件则显示修改状态,test2.txt 文件显示新增状态,文件 夹 test21 和 test211 以及里面的 test211.txt 文件 都显示为新增状态。 选择 将 test 文件夹 svn 还原, 则新增状态下的文件夹或者文件显示为无版本 控制状态,原先的 test.txt 还原为常规常态。 4、右 键 test 文件夹合并 test2 文件夹, 选择全递归, 结果和 3 一样。 但
14、是我们之前的 test 文件夹和仓库上的 test 的内容是一致的, 如果不一致, 那么选全递归, 是已仓库版本为标准。 选工作副本, 顾名思义, 则以 你 本地的工作副本文件为主, 分支上有而工作副本中没有的文件夹或文件 则不进行比较合并。 5、右键 test 文件夹合并 test2 文件夹,选择直接子节点,包含文件夹。 则 test 文件夹中原先的 test.txt 文件显示为修改状态,test2.txt 文件显示 为新增状态,test21 文件夹显示为新增状态,但是其里面内容则为空, 那么就证明了分支中 test21 文件夹以下的内容并没有合并到主干 test 中 来, 合并行为只是选取
15、了当前目录。 选择将 test 文件夹 svn 还原, 则 新 增状态下的文件夹或者文件显示为无版本控制状态, 原先的 test.txt 还原 为常规状态。 6、右键 test 文件夹合并 test2 文件夹,选择仅文件子节点。则 test 文件 夹中原先的 test.txt 文件显示为修改状态, test2.txt 文件显示为新增状态 , 分支 test2 中的 test21 文 件夹没有合并到 test 中 来。 选择将 test 文件夹 svn 还原, 则新增状态下的文件显示为无版本控制状态, 原先的 test.txt 还原 为常规状态。 7、右键 test 文件夹合并 test2 文件
16、夹,选择仅此项。则 test 文件夹显示 为修改状态, 但是内容没有任何改动。 将 test 文件夹 svn 还原, 则该文 件夹显示为常规状态。 只 记录 合并( 阻止 这些版 本将 来被合 并) 选择此项意味着并没有实际的合并动作,只是在将来的合并过程中,svn 将 过滤掉此版本的修改动作。例如,我在合并的过程中,选择对分支的 23 版本只 记录合并 (阻止这个版本将来被合并) , 那么 23 版本并不会合并到主干中。 在以 后的合并中,如果选择合并分支的 22 到 24 版本,那么 23 版本将被忽略,我们 也可以看到,在选择版本的对话框上,23 版本的字体是灰色的。所以要慎重使 用这个
17、选项,一旦使用了,那么表示这个版本在以后的合并中就不能再使用了。 忽略祖先: 如果在分支上有一个文件曾经被删除过, 后来又加了一个同文件名的 文件, 那么在 merge 的 时候 svn 会识别到这两个文件不是同一个祖先而直接覆盖 旧文件增加新文件。 而实际上我是要对这两个不同祖先的文件进行合并的, 这个 时候就需要使用 svn merge -ignore-ancestry 忽 略祖先来进行合并才能保证正确。 实 例: 1、 将主干 test 创建分支 test1 ; 2、 将 test1 文件夹下的 test.txt 文件删除,提交; 3、 在 test1 下创建文件 test.txt,提交
18、; 4、 将 test1 合并到主干 test ,如果默认选择,则提示将 test1 中的 test.txt 文件替 换 test 文件夹中的 test.txt 文件; 如果选择了忽 略祖先, 那么系统将把两个 test.txt 作比较,必要时提示冲突。 carriage return 是一个符 号(指回车符号 CR) , 而一般在代码文件或文体文件里 (WINDOWS 下)里换行是 CR 和 LF (即rn 或十六进制码 0D 0A) ,而你行中 只有 CR,所以将要加 一个 LF (即 OA) 。说 得很明确了,其实 LF 就是 line feed 的简写。whitespace 包括 line feeds, tabs, spaces, and carriage returns 。