Subversion版本控制 — 分支和合并(三)
概要
一种项目开发流程:
(1)各开发成员建立自己的分支,并在此分支上开发。
(2)各开发成员把分支合并到主干上,形成较为稳定的版本。
(3)各个成员重新从主干上建立新的分支,回到第一步。
(4)循环,直到工程结束。
分支
(一)分支(branch)的定义
A line of development that exists independently of another line, yet still shares a common history
if you look far enough back in time. A branch always begins life as a copy of someting, and moves
on from there, generating its own history.
(二)为什么要有分支
创建分支最大的目的是跟主线进行并行开发而不影响主线的开发。
This allows you to save your half-broken work frequently without interfering with others, yet you
can still selectively share information with your collaborators.
For projects that have a large number of contributors, it's common for most people to have working
copies of the trunk. Whenever someone needs to make a long-running change that is likely to
disrupt the trunk, a standard procedure is to create a private branch and commit changes there
until all the work is complete.
需要开发新的特性时,直接在主线trunk上开发可能导致其不稳定或不可用,这时可以创建分支来开发。
(三)分支的生命周期
1. 何时创建?
For projects that have a large number of contributors, it's common for most people to have working
copies of the trunk. Whenever someone needs to make a long-running change that is likely to
disrupt the trunk, a standard procedure is to create a private branch and commit changes there
until all the work is complete.
2. 分支的维护
The good news it that you won't interfere with others. The bad news is that it's very easy to drift too
far apart. Remember that one of the problems with the "crawl in a hole" strategy is that by the time
you're finished with your branch, it may be near-impossible to merge your changes back into the
trunk without a huge number of conflicts.
Instead, you and other menbers can continue to share changes as you work. It's up to you to
decide which changes are worth sharing.Subversion gives you the ability to selective copy
changes between branches. And when you're completely finished with your branch, your entire
set of branch changes can be copied back into the trunk.
(四)分支的创建
项目project1的文件放在trunk目录下,现在在branches目录下创建分支zhangskd:
svn copy http://localhost/svn/project1/trunk http://localhost/svn/project1/branches/zhangskd \
-m "Creating a private branch of /project1/trunk."
显示:Committed revision ***.
表示新创建的分支zhangskd的版本号为***。
合并
(一)合并(merge)的定义
Instead of printing the differences to your terminal, it applies them directly to your working
copy as local modifications.
(二)合并的原理
A better name for the command might have been svn diff-and-apply, because that's all that
happens: two repository trees are compared, and the differences are applied to a working
copy.
svn merge有三个参数:
1)An initial repository tree (often called the left side of the comparsion)
2)An final repository tree (often called the right side of the comparsion)
3)A working copy to accept the differences as local changes (often called the target)
所以合并的格式:svn merge leftside rightside target
为什么merge应该叫diff-and-apply?
leftside和rightside分别是两个版本树,对应于两个不同的版本,即URL@REV,如果它们的URL
相同,还可以表示为-r REV1:REV2 URL。可以用diff来查看这两个版本树的区别:
svn diff URL@REV URL@REV
svn diff -r REV1 : REV2 URL
svn diff leftside rightside ,假设得到的修改集B。
target是要合并修改集B的分支。假设target在上次合并后,又产生了本地修改集A。
那么本次合并要做的事情就是:把修改集B也当成本地修改集,应用到target上!
1)如果修改集A和修改集B不重叠,可以顺利合并。此时target和上次合并时的版本相比,就有了
两个本地修改集A和B,commit后可以得到新的版本。
2)如果修改集A和B有重叠,会产生冲突。这个时候就需要解决冲突后,才能顺利合并。
这个时候会产生三个文件:filename.working,filename.left,filename.right。这三个文件
和svn update检测到冲突后产生的三个文件有着相同的作用。
当本地修改集A为空的时候,不会有冲突出现。
To begin with, assume that your working copy has no local edits. When you svn update to a
particular revision, the changes set by the server will always apply "cleanly" to your working
copy. The server produces the delta by comparing two trees: a virtual snapshot of your
working copy, and the revision tree you're interested in. Because the lefthand side of the
comparision is exactly equal to what you already have, the delta is guaranteed to correctly
convert your working copy into the righthand tree.
(三)分支的合并
合并分支的时候,需要指定要一个目标,用来接收这些修改集,如果没有,则默认:
svn merge requires a working-copy path as a target, i.e. a place where it should apply the
tree-changes. If the target isn't specified, it assumes you are trying to perform one of the
following common operations:
1)You want to merge directory changes into your current working directory.
2)You want to merge the changes in a specific file into a file by the same name which
exists in your current working directory.
例1: svn merge http://svn.example.com/repos/branch1@150 \
http://svn.example.com/repos/branch2@212 \
my-working-copy
例2:svn merge -r 100:200 http://svn.example.com/repos/trunk my-working-copy
例3:svn merge -r 100:200 http://svn.example.com/repos/trunk
和取消本地修改一样,可以用svn revert来取消合并。
可以用svn delete来删除分支。
(四)合并的最佳使用方式
1)手动记录合并
主线和分支都在不断的变化着,当我们要把主线的一些特性合并到分支上,应该从哪个版本开始合并?
假设分支的创建版本为10,且它已经合并主线版本10~20的变化了,这个时候应该从主线版本21开始
合并,才不会导致重复合并。
因为SVN并不会自动为我们记录合并的信息,所以我们需要手动记录。
当每次提交合并时,可以在日志中说明本次合并的范围,比如此次分支合并了主线的哪些版本。
这样,当下次分支要合并主线的变化时,就可以知道要从主线的哪个版本开始。
2)预览合并
可以用--dry-run和svn status来预览合并,提前知道本次合并是否会产生冲突。
例 svn merge --dry-run -r 10 : 20 http://192.168.1.1/svn/project/trunk
svn status
# nothing printed, working copy is still unchanged, no conflict will happen
The --dry-run option doesn't apply any local changes to the working copy. It only shows status
code that would be printed in a real merge.
3)常用分支模式
3.1) 发布分支
发布分支(Release Branch)指的是创建分支主要为了发布新的版本,其过程如下:
开发者提交所有的新特性到主干,在主干上开发。
当小组认为软件已经做好发布准备(1.0版),主干/trunk被拷贝到分支/branches/1.0。
项目组并行工作:一个小组对分支进行测试,另一小组在主干上继续新的工作(2.0)。如果一个bug
在任何位置被发现,错误修正则需来回合并。
当测试结束时,分支作为标签发布,/branches/1.0拷贝到/tags/1.0.0,这个标签被打包发布给客户。
继续在/trunk上为版本2.0工作,bug修正继续从/trunk运送到/branches/1.0,如果积累了足够的bug
修正,则可以发布1.0.1版本:拷贝/branches/1.0到/tags/1.0.1,标签被打包发布。
当2.0完成时,重复上述测试、打标签、发布。
3.2) 特征分支
特征分支(Feature Branch)主要用于开发新的特性,同时不影响主线的稳定性和可用性。
Unlike release branches (which may need to be supported forever), feature branches are born,
used for a while, merged back to the trunk, then ultimately deleted. They have a finite span of
usefulness.
要注意保持特征分支同步于主干,因为在一个分支上工作数周或几个月有很大风险,这个时候主干
和分支可能会有大量的冲突!
This situation is best avoided by regularly merging trunk changes to the branch. Make up a
policy: once a week, merge the last week's worth of trunk changes to the branch.
Author
zhangskd @ csdn
Reference
svn book