﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Sealyu-随笔分类-版本控制</title><link>http://www.blogjava.net/sealyu/category/30671.html</link><description>--- The devil's in the Details</description><language>zh-cn</language><lastBuildDate>Wed, 21 Apr 2010 16:44:27 GMT</lastBuildDate><pubDate>Wed, 21 Apr 2010 16:44:27 GMT</pubDate><ttl>60</ttl><item><title>SVN—patch的应用(转)</title><link>http://www.blogjava.net/sealyu/archive/2010/04/21/319039.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 21 Apr 2010 15:21:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2010/04/21/319039.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/319039.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2010/04/21/319039.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/319039.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/319039.html</trackback:ping><description><![CDATA[1.create patch
<br />
使用create patch可
以生成一个或者多个修改过的文件和当前版本差异的patch（支持目录树）
<br />
通常情况下，create patch将
修改保存为.patch或.diff文件
<br />
可以将.patch或.diff文件的内容复制出来，发给需要审查的人
<br />
.patch或.diff文件中记录了发生这个patch的版本号以及具体修改的内容
<br />
针对某个文件或某几个文件的若干种修改，可以生成多个.patch或.diff文件
<br />
2.apply patch
<br />
可以将.patch或.diff文件应用到对应版本的项目，就像打补丁一样
<br />
同一个项目/文件夹下，可以选择应用需要的patch
<br />
通常来说，应用一个patch时文件版本和生成这个patch时文件的版本是一致的；如果不一致，也可以强制应用，svn会自动进行diff（这时候需要手动合并）
<br />
linux下，可以使用系统的patch命令来应用patch，eg: patch -p0
&lt;xxx.patch
<br />
3.使用
<br />
暂时不需要提交或不允许提交的修改，可以选择create patch来保存修改的内容
<br />
选择create patch来
保存修改的内容并且提交patch，通过审查后，(在服务器端)应用patch
<br />
当一个功能有多种解决方案时，可以生成多个patch，（提交后）分别经过测试，再
决定应用哪个patch
<br />
多个功能分别需要改同一个文件的不同地方（即没有同一行），可以做成多个patch，
应用patch的顺序没有要求（在linux下应用也一样成功，只是会生成多个.orig文
件）
<br />
多个连续性的功能，他们修改的文件都与一个base作patch，例：p1在v1的
基础上开发v2，生成v2和v1之间的patch1；p2在v2的基础上开发v3，生成v3和v1之间的patch2，这样只要应用patch2也就应用
了patch1。
<br />
4.带来的问题
<br />
一个较早的patch，在经过多轮提交后，如果想再要应用，需要严格的diff
<br />
如果两个patch分别改了同一行代码，应用第一个patch后要再应用第二个patch时，
仍然需要diff。如果在linux下，会产生冲突，生成.orig和.rej两个文件（此时仍然需要手动进行比较合并）
<br />
第3部分提到的连续性，要准确的预见到，比较困难
<br />
第3部分提到的多个连续的功能，后做的功能的某个文件更新了先做的功能的内容，但先做的功能可能还涉及到其他文件，容易造成漏更新文件的情况
<img src ="http://www.blogjava.net/sealyu/aggbug/319039.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2010-04-21 23:21 <a href="http://www.blogjava.net/sealyu/archive/2010/04/21/319039.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVN提交工作注意事项</title><link>http://www.blogjava.net/sealyu/archive/2009/09/03/293717.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 03 Sep 2009 03:21:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/09/03/293717.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/293717.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/09/03/293717.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/293717.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/293717.html</trackback:ping><description><![CDATA[Sealyu 2009-9-3<br />
<br />
公司让总结一下SVN日常提交工作时需要注意的事项，结合看到的一片很好的帖子，自己做了部分修改。<br />
帖子地址：http://www.cnblogs.com/chenlong828/archive/2008/09/22/1296193.html 。 感谢作者dreamland让我节省了不少时间。<br />
<br />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Word.Document" />
<meta name="Generator" content="Microsoft Word 12" />
<meta name="Originator" content="Microsoft Word 12" />
<link rel="File-List" href="file:///C:%5CDOCUME%7E1%5Cyuhaibo%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml" />
<link rel="themeData" href="file:///C:%5CDOCUME%7E1%5Cyuhaibo%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx" />
<link rel="colorSchemeMapping" href="file:///C:%5CDOCUME%7E1%5Cyuhaibo%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml" /><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
EN-US
ZH-CN
X-NONE
</xml><![endif]--><!--[if gte mso 9]><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:""@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{
mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
font-size:10.5pt;
font-family:"Times New Roman","serif";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:21.0pt;
font-size:10.5pt;
font-family:"Times New Roman","serif";}
.MsoChpDefault
{
font-size:10.0pt;
mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{}
@list l0:level1
{
margin-left:21.0pt;
text-indent:-21.0pt;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.0pt;
font-family:"Times New Roman","serif";}
</style>
<![endif]-->
<p><strong><span style="font-size: 14pt; font-family: 宋体;">一．提交之前先更新</span></strong></p>
<p style="margin-left: 21pt; text-indent: -21pt;"><span><span>1.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span>SVN<span style="font-family: 宋体;">更新的原则是要随时更新，随时提交。当完成了一个小功能，能够通过编译并且自己测试之后，谨慎地提交。</span></p>
<p style="margin-left: 21pt; text-indent: -21pt;"><span><span>2.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">如果在修改的期间别人也更改了</span>svn<span style="font-family: 宋体;">的对应文件，那么</span>commit<span style="font-family: 宋体;">就可能会失败。如果别人和自</span> <span style="font-family: 宋体;">己更改的是同一个文件，那么</span>update<span style="font-family: 宋体;">时会自动进行合并，如果修改的是同一行，那么合并时会产生冲突，这种情况就需要同之前的开发人员联系，两个人一起协商解决冲突，解决冲突之后，需要两人一起测试保证解决冲突之后，程序不会影响其他功能。</span></p>
<p style="margin-left: 21pt; text-indent: -21pt;"><span><span>3.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">在更新时注意所更新文件的列表，如果提交过程中产生了更新，则也是需要重新编译并且完成自己的一些必要测试，再进行提交。这样既能了解别人修改了哪些文件，同时也能避免</span>SVN<span style="font-family: 宋体;">合并错误导致代码有错</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体;">二．保持原子性的提交</span></strong></p>
<p><span style="font-family: 宋体;">每次提交的间歇尽可能地短，以几个小时的开发工作为宜。例如在更改</span>UI<span style="font-family: 宋体;">界面的时候，可以每完成一个</span>UI<span style="font-family: 宋体;">界面的修改或者设计，就提交一次。在开发功能模块的时候，可以每完成一个小细节功能的测试，就提交一次，在修改</span>bug<span style="font-family: 宋体;">的时候，每修改掉一个</span>bug<span style="font-family: 宋体;">并且确认修改了这个</span>bug<span style="font-family: 宋体;">，也就提交一次。我们提倡多提交，也就能多为代码添加上保险。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体;">三．提交时注意不要提交本地自动生成的文件</span></strong></p>
<p><span style="font-family: 宋体;">一般配置管理员都会将项目中一些自动生成的文件或者与本地配置环境有关的文件屏蔽提交（例如</span>eclipse<span style="font-family: 宋体;">中的</span>.classpath<span style="font-family: 宋体;">文件等）。如果项目中没有进行这方面的配置来强行禁止提交这样的文件，请自觉不要提交这样的文件。提交了这样的文件后，别人在更新后就可能与本地的环境冲突从而影响大家的工作。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体;">四．不要提交不能通过编译的代码</span></strong></p>
<p><span style="font-family: 宋体;">代码在提交之前，首先要确认自己能够在本地编译。如果在代码中使用了第三方类库，要考虑到项目组成员中有些成员可能没有安装相应的第三方类库。项目经理在准备项目工作区域的时候，需要考虑到这样的情况，确保开发小组成员在签出代码之后能够在统一的环境中进行编译。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体;">五．不要提交自己不明白的代码</span></strong></p>
<p><span style="font-family: 宋体;">代码在提交入</span>SVN<span style="font-family: 宋体;">之后，你的代码将被项目成员所分享。如果提交了你不明白的代码，你看不懂，别人也看不懂，如果在以后出现了问题将会成为项目质量的隐患。因此在引入任何第三方代码之前，确保你对这个代码有一个很清晰的了解。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体;">六．提前协调好项目组成员的工作计划</span></strong></p>
<p><span style="font-family: 宋体;">项目经理应该合理分配工作计划。每个成员在准备开始进行某项功能的修改之前，如果有可能，先跟工作小组的成员谈谈自己的修改计划，让大家都能了解你的思想，了解你即将对软件作出的修改，这样能尽可能的减少在开发过程中可能出现的冲突，提高开发效率。同时你也能够在和成员的交流中发现自己之前设计的不足，完善你的设计。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体;">七．对提交的信息采用明晰的标注</span></strong></p>
<p><span style="font-family: 宋体;">在一个项目组中使用</span>SVN<span style="font-family: 宋体;">，如果提交空的标注或者不确切的标注将会让项目组中其他的成员感到很无奈，项目经理无法很清晰的掌握工作进度，无法清晰的把握此次提交的概要信息。在发现错误后也无法准确的定位引起错误的文件。所以，在提交工作时，要填写明晰的标注，能够概要的描述所提交文件的信息，让项目组其他成员在看到标注后不用详细看代码就能了解你所做的修改。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体;">八．慎用锁定功能</span></strong></p>
<span style="font-size: 10.5pt; font-family: 宋体;">在项目中要慎用锁定的功能，在你锁定了一个文件之后别人就无法继续修改提交该文件，虽然可以减少冲突的发生率，但是可能会影响项目组中其他人员的工作。平时只有在编辑那些无法合并的文件（例如图片文件，</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">flash</span><span style="font-size: 10.5pt; font-family: 宋体;">文件等）时，才适当的采用锁定操作。</span><br />
<br />
<img src ="http://www.blogjava.net/sealyu/aggbug/293717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-09-03 11:21 <a href="http://www.blogjava.net/sealyu/archive/2009/09/03/293717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>五个使用SVN的好习惯（5 SVN best practices）</title><link>http://www.blogjava.net/sealyu/archive/2009/09/02/293662.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 02 Sep 2009 13:47:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/09/02/293662.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/293662.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/09/02/293662.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/293662.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/293662.html</trackback:ping><description><![CDATA[<p>Versioning systems like CVS, <a href="http://www.iovene.com/please-drop-svn/">SVN</a> or <a href="http://www.iovene.com/darcs-the-source-code-management-system-of-the-future/">Darcs</a>
are very important tools, that no serious programmers can omit to use.
If you started a project without using any versioning tools, I really
recommend that you start using one immediately; but I&#8217;m not discussing
this right now.</p>
<p>I would like to point your attention to some best practices that I recommend when working in a team.
</p>
<ol>
    <li><em><strong>Don&#8217;t use versioning like it were a backup tool.</strong></em>
    <p>I&#8217;ve heard this question too often: &#8220;Have you put your code safely
    on SVN?&#8221;. That&#8217;s a bad question. Storing code to an SVN server is not
    meant for safety, i.e. for fear of losing it. You are talking about
    something else, and that&#8217;s called backup. Take Darcs, a not so popular
    versioning system. It can start without a server, and you can just run
    it locally on your machine without launching any daemon whatsoever. A
    faulty hard drive can still make you lose all your work, of course.
    That&#8217;s why you have to do backups, of course, but they don&#8217;t have
    anything to do with versioning. Hence, committing to the repository
    once a day, before taking off home, e.g., is not an acceptable
    practice, <em>especially</em> if you work in a team. Doing that would
    be like making a daily backup. An SVN commit, instead, has to have a
    meaning of some sort, not just &#8220;Ok, let&#8217;s store to the SVN server the
    work of today&#8221;. Moreover, sometimes, if the schedule is tough and the
    cooperation is tight, you need to commit very often so your peer will
    keep up with you all the time, and not just find out, at evening, that
    he&#8217;s got dozens conflicts after checking out your code.</p>
    </li>
    <li><em><strong>Commit as soon as your changes makes a logical  unit.</strong></em>
    <p>How often should you commit? Theres no such thing as committing too
    often, or too rarely. You should commit each time your changes
    represent a logical unit, i.e. something that makes sense. Usually that
    happens because you&#8217;re following a plan, when coding (because you are,
    aren&#8217;t you?). So, you find out a bug in the trunk, plan a strategy
    about how to fix it, fix it, and then commit. This makes sense because
    that&#8217;s a commit that fixes a bug. So that revision X is buggy, while
    revision X+1 is not. Don&#8217;t be shy about committing too often. Should
    you just find an insignificant typo in a debug string, or in a comment,
    don&#8217;t be afraid of committing just to fix that. Nobody will be mad at
    you for being precise. Consider the extreme situation in which, after
    months and months, you may want to remember &#8220;What was the revision
    where I fixed that typo in that debug string?&#8221;. If you dedicated one
    signle commit for the actual <em>finite</em> logical unit of
    correcting the typo, you can just scroll back your changelog and find
    it. But what often happens, is that people will be doing something
    else, and, while doing that something else, will notice the type, and
    correct it, and basically merge that correction with the rest of the
    commit, making that thing losing visibility. To make it simple: your
    SVN comments shouldn&#8217;t explain that you did more than one thing. If
    your SVN comment looks like &#8220;Fixing bugs #1234 and #1235&#8243; or &#8220;Fixing
    bug #4321 and correcting typo in debug sting&#8221; then you should&#8217;ve used
    two commits.</p>
    </li>
    <li><em><strong>Be precise and exhaustive in your commit comments.</strong></em>
    <p>The second most annoying thing ever is committing with blank
    comments. If you&#8217;re working in a team, your peer developers will be
    frustrated about it and possibly mad at you, or will label you in a bad
    way; possibly publicly humiliate you. If you&#8217;re working alone, you will
    experience what you&#8217;re hypothetical development companions would have:
    frustration in not being able to easily track down what a certain
    commit did. Comments in commits are important. Please be precise and
    explain in detail everything you did. In the optimal case, I shouldn&#8217;t
    need to read your code.</p>
    </li>
    <li><em><strong>Never ever break the trunk.</strong></em>
    <p>This is probably the most annoying thing when dealing with people
    who can&#8217;t use versioning. Breaking the trunk is an habit that will
    quickly earn you the hatred of your colleagues. Think about it: if you
    commit a patch that breaks the trunk, and then I check it out, what am
    I going to do? The project won&#8217;t build so I either have to fix it, or
    come to your desk and complain to you. In both cases I&#8217;m wasting some
    time. And consider the first case again: what should I do after fixing
    your broken code? Commit it? Sending you a diff? If I&#8217;ll commit,
    chances are that you&#8217;ll have conflicts when you checkout, and you&#8217;ll
    have to waste time in resolving them. Maybe sending you a patch would
    be the best way, but still it&#8217;s a waste of time for the both of us. So
    the thing is: before committing, ALWAYS double check! Make a clean
    build and make sure that it builds. And don&#8217;t forget to add files! It&#8217;s
    a very common mistake: committing good code, but forgetting to add a
    file. You won&#8217;t realize, because the thing builds, but when I&#8217;ll
    checkout, I&#8217;ll have troubles, because of missing file(s). If you&#8217;re
    using Darcs, just make a &#8220;darcs get&#8221; in a new directory, and then build.</p>
    </li>
    <li><em><strong>Branch only if needed.</strong></em>
    <p>There are some ways to handle branches, but here&#8217;s my favorite. The
    most of the work should happen in the trunk, which is always sane, as
    stated by the previous practice, and the patches should always be
    small, so that they can be reviewed very easily. If you find yourself
    in the situation of needing to write a large patch, then you should
    branch it. In that way you can have small patches that will break your
    branch over the time, but they can be easily reviewed. After the
    process is completed, i.e. you&#8217;ve achieved your goal of fixing a bug or
    implementing a new feature, you can test the branch thoroughly, and
    then merge it to the trunk.</p>
    </li>
</ol>
<img src ="http://www.blogjava.net/sealyu/aggbug/293662.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-09-02 21:47 <a href="http://www.blogjava.net/sealyu/archive/2009/09/02/293662.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分支模式在SVN环境下的应用（转）</title><link>http://www.blogjava.net/sealyu/archive/2009/09/02/293533.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Wed, 02 Sep 2009 01:46:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/09/02/293533.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/293533.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/09/02/293533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/293533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/293533.html</trackback:ping><description><![CDATA[<h3>关于分支模式</h3>
<p>并行软件开发是企业级环境下软件开发的一种不可避免的模式，这种开发模式可以说是任何大中型软件产品和项目所必需的。然而，并行开发在为我们的开发效率提高保证的同时，也会给我们的开发管理带来诸多问题：</p>
<p>* 什么时候进行分支？ <br />
* 什么时候进行合并？ <br />
* 如何选择有效的分支策略？ <br />
* 如何保证不同分支上的代码同步问题？ <br />
* 如果建立对分支访问控制的授权机制？ <br />
* 如何避免频繁的合并冲突？ <br />
* 如何处理被复用的代码？ <br />
* &#8230;&#8230;</p>
<p>可以说并行开发中的分支与合并是一个涉及到环境、方法和技术平台等诸多因素的综合性难题，在这种场合下，&#8220;模式(Pattern)&#8221;可能是解决上述
问题的一个很好的工具。所谓模式，其实就是解决某一类问题的方法论。你把解决某类问题的方法总结归纳到理论高度，那就是模式。Alexander给出的经
典定义是：每个模式都描述了一个在我们的环境中不断出现的问题，然后描述了该问题的解决方案的核心。通过这种方式，你可以无数次地使用那些已有的解决方
案，无需在重复相同的工作。</p>
<p>在不同的领域有不同的模式，具体到并行开发领域，&#8220;分支模式&#8221;是专门针对并行开发环境下分支及合并作业中的各种不同的操作方法抽象出来的一套方法论。其主要由以下几部分组成:</p>
<p><strong>结构模式</strong>——通过约束和指导分支/代码线的整体结构，实现并行开发的组织结构、开发模式及开发过程的约束和指导。</p>
<p><strong>规则模式</strong>——通过对特定分支/代码线实施的约束，实现对该分支/代码线相关的操作进行约束，如访问控制及合并等操作的约束。</p>
<p><strong>创建模式</strong>——提供对分支/代码线创建的约束</p>
<p><strong>反模式</strong>——以反例的方式展示并行开发中常见的行为误区和陷阱，并提供有效的解决方案。</p>
<p>分支模式在并行开发中的应用难点有两个：一是如何根据企业的实际情况选择适合的分支模式，二是如何构建一个技术平台来将这些分支模式的理论和方法有
效的应用于实践。为此，我们专门在此开辟专栏和大家分享并行开发中分支模式相关的理论、方法以及如何将这些理论和方法付诸实现的相关实践。</p>
<h3>主线（结构模式）</h3>
<p><strong>一、分支模式的相关定义</strong></p>
<p><strong>模式 </strong>主线</p>
<p><strong>别名</strong> 主干、主锚线、本线、地线（Main Trunk, Main Anchor Line, Home Line, Ground Line ）</p>
<p><strong>场景</strong></p>
<p>在开发和维护周期中，因为各种原因需要创建多条代码线，典型的代码线是发布线、维护线和集成线。这在采用每发布代码线、并行维护/开发线和重叠发布线 (或者其任何变形模式)的情况下尤为如此。随着项目的进行，会创建出越来越多的代码线，从而导致项目的版本树越来越宽。</p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/234621O17-0.gif" alt="" height="288" width="475" /></p>
<p>连续的瀑布式分支（应该避免的情况）</p>
<p><strong>问题 </strong></p>
<p>怎样确保当前活动代码线的数量在可控范围内，以及避免项目的版本树过宽过深？</p>
<p><strong>动机 </strong></p>
<ul>
    <li>通常，每条代码线在某个时间点需要将变更集合并至其父分支。所以越多的代码线就意味着更多的合并，而越多的合并意味着越多的同步工作。</li>
    <li>当后续的版本发布时，看起来只有在当前版本的代码线上开创一个新的分支才算是合理的。</li>
</ul>
<p><strong>解决方案 </strong></p>
<p>在每一个分支树中保持一个&#8220;主&#8221;分支或代码线作为主干，而不是持续的瀑布式从分支创建分支从而使分支树变得宽广而笨重（在每一对父子分支之间需要大量的同步工作）</p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/2346215350-1.gif" alt="" height="245" width="484" /></p>
<p>拥有主线的瀑布式分支</p>
<p>当为主发布创建代码线的时刻来到时，我们不会从前一个发布线创建新的发布线，而是将先前的发布线合并回主线，然后再从主线创建新的发布线。 <br />
为特定代码线或分支合并回来的过程被称为&#8220;主线化&#8221;、&#8220;主干化&#8221;、&#8220;归位&#8221;、&#8220;锚定&#8221;或&#8220;接地&#8221;（"mainlining," "trunking," "homing," "anchoring," or "grounding."）。</p>
<p><strong>变种 稳定接收线</strong>（也称为稳定主线、主集成线和基础集成线（Stable Mainline, Main Integration Line, Base Integration Line））</p>
<p>保持一个稳定的，可靠的主要开发主干可以用来从其他代码线导入（接收）稳定基础。在代码线上不会直接发生开发工作，所有集成工作必须来自其他代码线（不是一个单独的离散的活动分支）。这个规则唯一的例外是为了保证代码线构建和功能一致性的集成变更。</p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/23462152b-2.gif" alt="" height="170" width="426" /></p>
<p>（用以接收稳定基线的稳定主线——实际上就是通常所说的基线）</p>
<p><strong>LAG开发线</strong>（也称为主开发线、中央线和主流）</p>
<p>把主干作为最新的最好的（LAG）会一直进展的开发线，所有前面的发布的代码线都会在其退休后被合并入其中。主干作为下一步/最后的开发发布（不是
维护，而是开发，包括显著的改进和新特性）的开发线使用，因此当B2发布的工作已经准备好开始，而A1发布已经完成或逐渐停止，则建立一个新的分支来结束
A1的工作（见延迟分支），而LAG线则用来针对B2（最新的和最好的开发工作）发布的工作。</p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/234621M17-3.gif" alt="" height="115" width="478" /></p>
<p>（LAG开发主线）</p>
<p>对于特定代码线或分支合并到滞后（LAG）开发线的过程也可以称为"LAGging," "mainlining," "LAG-lining," or "mainstreaming."。</p>
<p>尽管作为一个主线使用，LAG线也可以作为主线与稳定接收线结合：</p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/23462145P-4.gif" alt="" height="192" width="489" /></p>
<p>（有一条稳定主线用于接收发布版本的LAG开发主线）</p>
<p><strong>二、模式的分析</strong></p>
<p>主线模式及其变种主要试图从分支的结构上约束其不合理的扩展和延伸，而尽量使主线成为其他代码线创建的来源及合并的目标。稳定接收线（也就是通常所
说的基线）用于接受并保存相对稳定的版本，通常情况下其只接受版本（通常情况下为直接保存版本的镜像而非合并操作）而不进行其他任何操作。</p>
<p><strong>三、主线模式在Subversion环境下的实现</strong></p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/2346212050-5.jpg" alt="" height="265" width="520" /></p>
<p>如上图所示实际上就是有一条基线伴随的LAG开发线模式，实现该模式相关的约束包括：</p>
<p>1、所有的代码线（不包括分支）都从主线创建</p>
<p>2、主线以外的代码线的合并操作都以主线为目标</p>
<p>3、基线只接受版本（直接保存版本的镜像而非合并操作）而不进行其他任何操作。</p>
<h3>宽松访问线（规则模式）</h3>
<p><strong>一、分支模式的相关定义</strong></p>
<p><strong>模式</strong> 宽松访问线（Relaxed-Access Line）</p>
<p><strong>问题</strong> 如何确定代码线访问控制规则的限制或排他程度？</p>
<p><strong>动机 </strong></p>
<ul>
    <li>如果许多开发者在代码线上工作，或某一些人缺乏经验，那严格的治理是必要的。</li>
    <li>如果代码线上发生的工作具有显著的风险级别或难度，则检入和合并需要更紧密的监控和/或验证。</li>
    <li>保证代码线一直处于完整的状态非常重要，这样就不会影响其它工作在代码线上的人们。</li>
    <li>如果代码线对应了特定提升级别（见阶段集成线）或生命周期阶段，这也许指明了对特定代码线验证一致性的必要性级别。</li>
</ul>
<p><strong>解决方案 </strong></p>
<p>如果代码线是用来开发或维护（而不是排它或集成），并且工作在代码线上的团队规模相对较小，人员富于经验并可靠，那么给开发者有相对宽松自由的区
域，让他们做他们已经知道如何去做的事情：在一起以及时的方式工作。使用最小检查和控制，但是要确保代码线所有者可以认真对待他的工作，并可以一直知道代
码线的状态以及确认完整性是否被特定风险/复杂开发任务危害。</p>
<p><strong>相关模式 </strong></p>
<p>MYOC（合并你自己的代码）及其变种PYOC（传递你自己的代码）是使用宽松访问线最常见的副产品（或原因），如果在你的环境中，风险较小，而且开发者合并自己的变更到代码线的交流通畅，那么我们有充足的理由使用宽松访问。</p>
<p><strong>二、对模式的分析</strong></p>
<p>这种访问模式通常适用于冲突不严重（如开发初期或彼此按模块独立开发）的情况，要求相关人员具备一定的水准以保证开发的质量，而在开发的后期通常不适用这种模式。</p>
<p><strong>三、宽松访问线（Relaxed-Access Line）在Subversion环境下的实现</strong></p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/2346215916-6.jpg" alt="" height="342" width="540" /></p>
<p>如上图所示（相关内容只是相关模式实现的一个实例，实际使用时可根据实际需求对角色及授权进行调整）：</p>
<p>1、代码线的所有者对代码线拥有完全的操作权限</p>
<p>2、主管及EPG成员仅对代码线拥有有限的操作权限（读）</p>
<p>3、除测试人员以外的项目成员都对代码线拥有完全的读写权限</p>
<p>4、代码线的所有者以及项目经理和配置经理拥有对代码线锁的权限</p>
<h3>大爆炸式集成（反模式）</h3>
<p><strong>一、分支模式的相关定义</strong></p>
<p><strong>陷入的误区</strong> 大爆炸集成</p>
<p><strong>别名</strong> 大怪兽集成</p>
<p><strong>症状 </strong></p>
<p>由于某种原因，一直不选择集成，直到（软件）要发布的时候
，才把所有的分支一下子全部交给倒霉的集成者进行集成。经常性的增量集成看起来是流行的常识性规则（亦称为：尽早且经常合并），大爆炸（的方式）显然在隔
离和避免风险方面达到了极致，这是大怪物地结束合并，结果不是一个&#8220;大爆炸&#8221;，而是以&#8220;哭泣&#8221;告终。</p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/234621J19-7.gif" alt="" height="216" width="479" /></p>
<p>大爆炸式的集成（需要避免的反模式）</p>
<p><strong>原因 </strong></p>
<p>一个原因是我们未能成功找到尽早集成和经常集成的地正确&#8220;节奏&#8221;和&#8220;脉搏&#8221;。有时&#8216;大怪兽式集成&#8217;是&#8220;整合恐惧症&#8221;带来的附加品，在尽力缩小合并数
量的时候，结果会是一个延期而至的可怕的复杂合并的结尾。因而，在这种情况下，&#8220;集成是魔鬼&#8221;
变成了自我实现的一种预言，并且在失败的恶性循环中不断加强。</p>
<p><strong>影响</strong></p>
<p>太多人都很熟悉所造成的后果，直到一切已经太晚，如系统不能正确的构建，无法通过测试，或部分代码与其它代码工作不能协同工作，我们才能发现这问
题。直到项目生命周期的下一个阶段，这些信息才得到交流，相关的风险和返工将会非常巨大，会导致&#8220;合并是魔鬼&#8221;或&#8220;合并恐惧&#8221;的心理。</p>
<p><strong>修复和预防 </strong></p>
<p>使用尽早经常性的集成或使用一个或更多的变种来确保以一定频率和间隔执行集成，以在时间充裕，额外工作较少时尽早分解风险和尽快交流问题区域。你可
以现在或者将来，或者由你自己决定何时付出，有规律的经常的集成可以迫使你在每次迭代和集成计划中只需要付出很少的努力，通过分解减少随时间积累的合并负
担，从而定义了健康项目的&#8220;脉搏&#8221;。</p>
<p><strong>二、模式的分析</strong></p>
<p>这种大爆炸式的集成在缺乏有效管理的团队中是经常发生的，我们经常可以看到这样的场景：明天就要发版本了（尤其是非计划的发布），今天所有的相关人员都一起合版本，于是大家惊讶的发现系统出现无数的合并冲突和缺陷，而在这种情况下，延迟发布几乎是唯一的选项了。 <br />
要避免这种最好的方式就是通过某种机制约束分支的周期和合并。</p>
<p><strong>三、大爆炸式集成在Subversion环境下的规避方式</strong></p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/2346214H8-8.jpg" alt="" height="196" width="540" /></p>
<p>如上图所示，在创建分支时添加如下约束：</p>
<p>1、创建分支时定义分支的周期（通常任务分支都是需要及时终结的），并强制终结</p>
<br />
<p>2、创建分支时定义分支的合并周期和约束方式（包括提醒和强制合并两种可选方式）</p>
<p>通过上述的约束，可以使分支/代码线及时的合并和终结，从而避免大爆炸式集成的发生</p>
<h3>代码所有权（规则模式）</h3>
<p><strong>一、分支模式的相关定义</strong></p>
<p><strong>模式</strong> 代码线所有权（Codeline Ownership）</p>
<p><strong>别名</strong> 分支所有权（Branch Ownership ）</p>
<p><strong>场景 </strong></p>
<p>作为一名程序员，在一组多代码线的环境下，并至少在一条代码线上开发。代码线规则已经为该代码线定义好检入/检出的规则。有些人要在代码线上进行某些工作，但是该规则并没有允许这样的操作，或者就是规则对一些特定事务的描述含糊不清。</p>
<p><strong>问题</strong></p>
<p>能影响代码线的动作能否执行？在保证代码线的完整性和连续性的同时，怎样做上面的决策?</p>
<p><strong>动机 </strong></p>
<ul>
    <li>&#8220;理论上，实践和理论是一致的；但在实践中，其两者却有极大的不同。&#8221;没有一个规则能够涵盖所有的情况。 代码线规则从理论上满足了需求，但是在实践中，则还有必要其他一些东西补充理论和实践之间的缺失。</li>
    <li>如果代码线规则不是很清楚，则开发人员需要将其定义清楚。</li>
    <li>代码线规则是会被违背的，不管是有意还是无意。</li>
    <li>代码线必须保持正确且连续的状态，以避免与正在进行的开发任务起相反的作用。.</li>
</ul>
<p><strong>解决方案 </strong></p>
<p>为每个代码线分配一名所有者（owner），其相应的职责如下</p>
<ul>
    <li>如果代码线的规则定义不清晰，则定义清楚;</li>
    <li>如果检入的配置项与代码线的规则相抵触，则决定让其保留在代码线中，还是回退到上一个版本</li>
    <li>制定相应的规则，防止代码线处于含糊不清状态或不适用实际情况</li>
    <li>在该代码线上，辅助或执行变更的集成</li>
    <li>决定何时对代码线进行冻结，解冻；何时代码线必须结束生命周期并且合并到主线（Mainline）中</li>
</ul>
<p>所有权（Ownership）并不一定意味着排他式的访问，但却表示用户认证访问控制。也许只有代码线的所有者才能检入文件（受限访问线）；或者，
其他人只要在检入前获得代码线所有者的同意，即可检入代码线，又或者在检入后立刻通知代码线所有者（宽松访问线）。代码线规则必须清楚地定义访问控制类型
相对应的所有权类型。通常来讲，在代码线上工作的开发人员越多，相应的所有权策略也越严格。同样地，限制程度与代码线包含活动的风险性或是复杂性，或是对
稳定性的要求成正比。在较小的项目和团队中的代码线中所包含较少的关键任务，在保证代码线完整性和连续性的前提下，提供比较随意，限制较少的访问控制策
略。</p>
<p><strong>变种 代码线专属（Codeline Dictatorship ）</strong></p>
<p>代码线的所有权中极其严格的一种形式，其配置项的检出和分支都是严格受限的，当然更包括检入。专属者可能是一个人，或是一个小组。一个常见的例子就
是&#8220;远程开发线&#8221;。远程开发人员可能被禁止从非远程分支中创建新的版本或是分支，因此，本地分支仅仅是&#8220;主人（master）&#8221;开发的地方。这实质上就是
ClearCase Multisite定义的&#8220;分支主人身份（branch mastership）&#8221;的概念。</p>
<p><strong>导致的场景 </strong></p>
<ul>
    <li>只有一个人对代码线的连续性和完整性负责。这样，代码线比较可能处于一种稳定的状态。</li>
    <li>保持所有者对代码线的状态负责，降低了代码线规则被践踏或代码线被用于错误目的的可能。</li>
    <li>代码线的概念完整性由一个头脑，也就是所有者维护，作为解决代码线问题的单一权威。</li>
</ul>
<p><strong>二、模式的分析</strong></p>
<p>代码线所有权/代码线专属模式强调的是代码线所有者对代码线的控制权，适用于由专人（或角色）对代码线内容进行全权负责的情况下使用</p>
<p><strong>三、代码线专属（Codeline Dictatorship ）在Subversion环境下的实现</strong></p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/2346213L6-9.jpg" alt="" height="367" width="555" /></p>
<p>如上图所示（相关内容只是相关模式实现的一个实例，实际使用时可根据实际需求对角色及授权进行调整）：</p>
<p>1、代码线的所有者对代码线拥有完全的操作权限</p>
<p>2、主管、项目经理及配置经理仅对代码线拥有有限的操作权限（读）</p>
<p>3、代码线的所有者拥有再授权的权限</p>
<h3>代码线规则（规则模式）</h3>
<p><strong>一、分支模式的相关定义</strong></p>
<p><strong>模式名称</strong> 代码线规则</p>
<p><strong>别名</strong> 每代码线规则</p>
<p><strong>适用环境</strong> 使用多条代码线开发软件的情况下。</p>
<p><strong>问题</strong> 开发人员如何知道需要将他们的代码存入哪条代码线中，并且何时保存？</p>
<p><strong>动机</strong></p>
<ul>
    <li>每条代码线都有不同的目的 ；</li>
    <li>代码线的名称通常能暗示其目的；</li>
    <li>代码线的名称通常不能全部表达代码线的使用要点；</li>
    <li>如果代码写入到错误的代码线，而这错误的变更必须要回退，导致生产率的降低；</li>
    <li>使用正规文档描述代码线的用法会很有帮助，但是需要额外的记录和维护；</li>
    <li>这个文档太过拘谨就会有一点过度规划和专横了；</li>
</ul>
<p><strong>解决方案</strong></p>
<p>除了给分支/代码线起一个有意义的名称之外，要给每条代码线明确目的，并使用简捷明了的策略描述其目的。其中应该包括以下一些要点：</p>
<ul>
    <li>代码线包含何种工作，例如：开发、维护、一种特定的版本、功能或是子系统；</li>
    <li>配置项在怎样的条件下才能被检入，检出，分支，合并；</li>
    <li>对于不同的个人，角色，组，代码线该设置怎样的读写权限的限制；</li>
    <li>导入/导出关系：代码应该从其它哪些代码线中接受变更，同时应该将变更应用于其它哪些代码线；</li>
    <li>代码线的生命周期或结束条件；</li>
    <li>预期的工作负载以及集成频率。</li>
</ul>
<p>让规则简短扼要：一个简单的经验方法是1-3段（各自25行25个字符，一页绝对是上限）。</p>
<br />
<br />
<p>请切记不是所有的代码线策略都需要上面所有的信息，只需要制定自己所需要的。一些版本控制工具允许在每个分
支、代码线的名称上附加详细的注解，这是存放合适简短代码线规则描述的理想地方。开发者可以通过包含代码线名称的命令来查看代码线规则，而无需在别的地方
找文档。否则，将代码线规则放在大家都知道的随手可得的地方（或许提供简单的命令或宏，对于给定代码线名称可以快速显示规则）。</p>
<p><strong>二、对模式的分析</strong></p>
<p>代码线规则这种模式实际上就是一种最基本的分支/代码线使用规范，它强调每条分支/代码线都应该以快捷而有效的方式记录其相关的信息，并且这些信息可以随时被方便的访问。</p>
<p>作为更进一步的要求，除了将相关信息记录在案，在某些情况下对其中部分内容（如分支的周期及合并的频率等）进行提醒甚至约束也是有其必要性的。</p>
<p><strong>三、宽松访问线（Relaxed-Access Line）在Subversion环境下的实现</strong></p>
<p><img src="http://www.svn8.com/uploads/allimg/090802/23462115T-10.jpg" alt="" height="358" width="370" /></p>
<p>如上图所示：</p>
<p>1、每条分支/代码线代码线创建时都有效的记录相关信息</p>
<p>2、对分支的生命周期和合并周期提供约束控制</p>
<p>注：上述功能的实现是基于在系统底层屏蔽了所有不受控的分支创建操作，而只能在特定应用系统内进行分支/代码线的创建，从而使所有分支/代码线相关操作都处于受控状态</p>
<br />
<img src ="http://www.blogjava.net/sealyu/aggbug/293533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-09-02 09:46 <a href="http://www.blogjava.net/sealyu/archive/2009/09/02/293533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVN—patch的应用(转)</title><link>http://www.blogjava.net/sealyu/archive/2009/08/14/291108.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Fri, 14 Aug 2009 01:04:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2009/08/14/291108.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/291108.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2009/08/14/291108.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/291108.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/291108.html</trackback:ping><description><![CDATA[1.create patch
<br />
使用create patch可以生成一个或者多个修改过的文件和当前版本差异的patch（支持目录树）
<br />
通常情况下，create patch将修改保存为.patch或.diff文件
<br />
可以将.patch或.diff文件的内容复制出来，发给需要审查的人
<br />
.patch或.diff文件中记录了发生这个patch的版本号以及具体修改的内容
<br />
针对某个文件或某几个文件的若干种修改，可以生成多个.patch或.diff文件
<br />
2.apply patch
<br />
可以将.patch或.diff文件应用到对应版本的项目，就像打补丁一样
<br />
同一个项目/文件夹下，可以选择应用需要的patch
<br />
通常来说，应用一个patch时文件版本和生成这个patch时文件的版本是一致的；如果不一致，也可以强制应用，svn会自动进行diff（这时候需要手动合并）
<br />
linux下，可以使用系统的patch命令来应用patch，eg: patch -p0 &lt;xxx.patch
<br />
3.使用
<br />
暂时不需要提交或不允许提交的修改，可以选择create patch来保存修改的内容
<br />
选择create patch来保存修改的内容并且提交patch，通过审查后，(在服务器端)应用patch
<br />
当一个功能有多种解决方案时，可以生成多个patch，（提交后）分别经过测试，再决定应用哪个patch
<br />
多个功能分别需要改同一个文件的不同地方（即没有同一行），可以做成多个patch，应用patch的顺序没有要求（在linux下应用也一样成功，只是会生成多个.orig文件）
<br />
多个连续性的功能，他们修改的文件都与一个base作patch，例：p1在v1的基础上开发v2，生成v2和v1之间的patch1；p2在v2的基础上开发v3，生成v3和v1之间的patch2，这样只要应用patch2也就应用了patch1。
<br />
4.带来的问题
<br />
一个较早的patch，在经过多轮提交后，如果想再要应用，需要严格的diff
<br />
如果两个patch分别改了同一行代码，应用第一个patch后要再应用第二个patch时，仍然需要diff。如果在linux下，会产生冲突，生成.orig和.rej两个文件（此时仍然需要手动进行比较合并）
<br />
第3部分提到的连续性，要准确的预见到，比较困难
<br />
第3部分提到的多个连续的功能，后做的功能的某个文件更新了先做的功能的内容，但先做的功能可能还涉及到其他文件，容易造成漏更新文件的情况
<img src ="http://www.blogjava.net/sealyu/aggbug/291108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2009-08-14 09:04 <a href="http://www.blogjava.net/sealyu/archive/2009/08/14/291108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SubVersion(SVN) 安装说明 </title><link>http://www.blogjava.net/sealyu/archive/2008/04/24/195637.html</link><dc:creator>seal</dc:creator><author>seal</author><pubDate>Thu, 24 Apr 2008 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/sealyu/archive/2008/04/24/195637.html</guid><wfw:comment>http://www.blogjava.net/sealyu/comments/195637.html</wfw:comment><comments>http://www.blogjava.net/sealyu/archive/2008/04/24/195637.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/sealyu/comments/commentRss/195637.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sealyu/services/trackbacks/195637.html</trackback:ping><description><![CDATA[作者：sealyu<br />
1. 简介<br />
SubVersion 是新一代的版本控制工具，不仅可以管理程序源代码，而且也可用于文档或其他相关资料的管理。<br />
2. 下载<br />
svnsetup.exe&nbsp;&nbsp; http://subversion.tigris.org<br />
客户端TortoiseSVN http://tortoisesvn.net/downloads <br />
3. 安装步骤<br />
&nbsp; 1）安装刚才下载的软件<br />
&nbsp; 下面假设svnsetup的安装目录为<br />
&nbsp;C:\Program Files\Subversion<br />
&nbsp;您想建svn库的文件夹为 E:\svn<br />
&nbsp;&nbsp;<br />
&nbsp; 2）创建库<br />
&nbsp; 在E:\svn下，右键-》TortoiseSVN-&gt;Create Repository here.<br />
会在此文件夹下创建一个版本库，生成所需的文件。<br />
&nbsp; 3）创建为Windows自动运行的服务<br />
&nbsp; Subversion 从1.4版本开始，可以以windows系统服务的形式在开机时自动运行。但Subversion安装程序还不能把自己安装成windows服务，需要我们自己进行手动安装，方法如下： 打开一个DOS命令窗口，执行如下命令：　　<br />
sc create svnserve binPath= "\"C:\Program Files\Subversion\bin\svnserve.exe\" --service --root E:\svn" displayname= "Subversion Repository" depend= Tcpip start= auto 　　<br />
其中，sc是windows自带的服务配置程序，参数binPath表示svnserve可执行文件的安装路径，由于路径中的"Program Files"带有空格，因此整个路径需要用双引号引起来。而双引号本身是个特殊字符，需要进行转移，因此在路径前后的两个双引号都需要写成\"<br />
-- service参数表示以windows服务的形式运行，--root指明svn repository的位置，service参数与root参数都作为binPath的一部分，因此与svnserve.exe的路径一起被包含在一对双引号当中，而这对双引号不需要进行转义。<br />
displayname表示在windows服务列表中显示的名字， depend =Tcpip 表示svnserve服务的运行需要tcpip服务，start=auto表示开机后自动运行。　　<br />
安装服务后，svnserve要等下次开机时才会自动运行。　　<br />
若要卸载svn服务，则执行 sc delete svnserve 即可。 &nbsp;<br />
4）配置访问权限<br />
&nbsp;1 配置仓库<br />
SVN的svnserve对于每个仓库，有一个独立的配置文件和独立的用户、权限管理。<br />
在这里仍然要保持配置文件svnserve.conf的独立，但是用户、权限管理是用统一的一个文件来存储。<br />
这样方便以后的管理和维护。<br />
另外要注意，即使svnserve服务已经运行，修改配置文件或者用户、权限管理文件，保存后马上生效，不需要重启服务。<br />
假设已经配置两个仓库: source1和source2,都在E:\svn下.<br />
我们在E:\svn下放两个文件:passwd.conf 和authz.conf<br />
1.1 配置source1仓库<br />
进入仓库目录<br />
1.2 修改配置<br />
你可以直接删除默认的svnserve.conf文件，然后使用下面的配置：<br />
编辑svnserve.conf<br />
[general]<br />
anon-access = none <br />
auth-access = write<br />
password-db = ..\..\passwd<br />
authz-db = ..\..\authz<br />
realm = My First Repository<br />
说明：<br />
anon-access = none #不允许匿名用户访问<br />
auth-access = write #通过验证的用户可以读和写<br />
password-db = ..\..\passwd#用户保存文件<br />
authz-db = ..\..\authz#权限管理文件<br />
realm = My First Repository #仓库名称<br />
1.3 配置source2仓库<br />
进入仓库目录<br />
1.4 修改配置<br />
你可以直接删除默认的svnserve.conf文件，然后使用下面的配置：<br />
编辑svnserve.conf<br />
[general]<br />
anon-access = none <br />
auth-access = write<br />
password-db = ..\..\passwd<br />
authz-db = ..\..\authz<br />
realm = My Second Repository<br />
如果有更多的仓库，可以类推配置。<br />
----------------------------------------------------------------------<br />
svnserve.conf的原始内容：<br />
### This file controls the configuration of the svnserve daemon, if you<br />
### use it to allow access to this repository. (If you only allow<br />
### access through http: and/or file: URLs, then this file is<br />
### irrelevant.)<br />
### Visit http://subversion.tigris.org/ for more information.<br />
[general]<br />
### These options control access to the repository for unauthenticated<br />
### and authenticated users. Valid values are "write", "read",<br />
### and "none". The sample settings below are the defaults.<br />
# anon-access = read<br />
# auth-access = write<br />
### The password-db option controls the location of the password<br />
### database file. Unless you specify a path starting with a /,<br />
### the file's location is relative to the conf directory.<br />
### Uncomment the line below to use the default password file.<br />
# password-db = passwd<br />
### The authz-db option controls the location of the authorization<br />
### rules for path-based access control. Unless you specify a path<br />
### starting with a /, the file's location is relative to the conf<br />
### directory. If you don't specify an authz-db, no path-based access<br />
### control is done.<br />
### Uncomment the line below to use the default authorization file.<br />
# authz-db = authz<br />
### This option specifies the authentication realm of the repository.<br />
### If two repositories have the same authentication realm, they should<br />
### have the same password database, and vice versa. The default realm<br />
### is repository's uuid.<br />
# realm = My First Repository<br />
----------------------------------------------------------------------<br />
2 用户管理<br />
2.1 创建用户存储文件<br />
编辑passwd<br />
2.2 设置用户帐号<br />
[users]<br />
harry = harryssecret<br />
sally = sallyssecret<br />
bote = botessecret<br />
说明：<br />
[users] #是必须的，标记为用户配置开始<br />
harry = harryssecret # harry 是用户名 ， harryssecret是密码。注意，是明文密码<br />
sally = sallyssecret # 同上<br />
bote = botessecret # 同上<br />
往后所以仓库的用户都在这里记录就可以了。至于那个用户，允许访问那个仓库，在权限管理里限制。<br />
3 权限管理<br />
3. 1 创建权限管理文件<br />
编辑authz.conf<br />
3.2 设置权限管理<br />
[groups]<br />
source1 = harry<br />
source2 = sally<br />
[source1:/]<br />
@source1 = rw<br />
@source2 = r<br />
<br />
[source2:/]<br />
@source2 = rw<br />
bote = rw<br />
<br />
<img src ="http://www.blogjava.net/sealyu/aggbug/195637.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sealyu/" target="_blank">seal</a> 2008-04-24 16:35 <a href="http://www.blogjava.net/sealyu/archive/2008/04/24/195637.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>