1<!-- 2 3 Licensed to the Apache Software Foundation (ASF) under one 4 or more contributor license agreements. See the NOTICE file 5 distributed with this work for additional information 6 regarding copyright ownership. The ASF licenses this file 7 to you under the Apache License, Version 2.0 (the 8 "License"); you may not use this file except in compliance 9 with the License. You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, 14 software distributed under the License is distributed on an 15 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 KIND, either express or implied. See the License for the 17 specific language governing permissions and limitations 18 under the License. 19 20--> 21 22<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" 23 "http://www.w3.org/TR/html4/strict.dtd"> 24<html> 25<head> 26<meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 27<title>Subversion Best Practices</title> 28<style type="text/css"> 29h1 { 30 text-align: center; 31} 32</style> 33</head> 34 35<body> 36 37<h1>Subversion Best Practices</h1> 38 39<p>This is a quick set of guidelines for making the best use of 40Subversion in your day-to-day software development work.</p> 41 42 43<h2>Use a sane repository layout</h2> 44 45<p>There are many ways to lay out your repository. Because branches 46and tags are ordinary directories, you'll need to account for them in 47your repository structure.</p> 48 49<p>The Subversion project officially recommends the idea of a "project 50root", which represents an anchoring point for a project. A "project 51root" contains exactly three subdirectories: <tt>/trunk</tt>, 52<tt>/branches</tt>, and <tt>/tags</tt>. A repository may contain 53only one project root, or it may contain a number of them.</p> 54 55<p><em>Book reference:</em> <a 56 href="http://svnbook.red-bean.com/svnbook/ch05s04.html#svn-ch-5-sect-6.1">Choosing 57 a Repository Layout</a>.</p> 58 59 60 61<!-- =================================================== --> 62 63<h2>Commit logical changesets</h2> 64 65<p>When you commit a change to the repository, make sure your change 66reflects a single purpose: the fixing of a specific bug, the addition 67of a new feature, or some particular task. Your commit will create a 68new revision number which can forever be used as a "name" for the 69change. You can mention this revision number in bug databases, or use 70it as an argument to <tt>svn merge</tt> should you want to undo the 71change or port it to another branch.</p> 72 73<p><em>Book reference:</em> "Subversion and Changesets" sidebar, 74 within <a 75 href="http://svnbook.red-bean.com/svnbook/ch04s03.html">chapter 76 4</a>.</p> 77 78<!-- =================================================== --> 79 80<h2>Use the issue-tracker wisely</h2> 81 82<p>Try to create as many two-way links between Subversion changesets 83and your issue-tracking database as possible:</p> 84 85<ul> 86<li>If possible, refer to a specific issue ID in every commit log message.</li> 87<li>When appending information to an issue (to describe progress, or 88 to close the issue) name the revision number(s) responsible 89 for the change.</li> 90</ul> 91 92<!-- =================================================== --> 93 94<h2>Track merges manually</h2> 95 96<p>When committing the result of a merge, be sure to write a 97descriptive log message that explains what was merged, something 98like:</p> 99 100 <pre>Merged revisions 3490:4120 of /branches/foobranch to /trunk.</pre> 101 102<p><em>Book reference:</em> <a 103 href="http://svnbook.red-bean.com/svnbook/ch04s03.html#svn-ch-4-sect-3.2">Tracking 104 merges manually</a>, and <a 105 href="http://svnbook.red-bean.com/svnbook/ch04s04.html#svn-ch-4-sect-4.1">Merging a whole branch to another</a>.</p> 106 107<!-- =================================================== --> 108 109<h2>Understand mixed-revision working copies</h2> 110 111<p>Your working copy's directories and files can be at different 112"working" revisions: this is a deliberate feature which allows you to 113mix and match older versions of things with newer ones. But there are 114few facts you must be aware of:</p> 115 116<ol> 117 118<li>After every <tt>svn commit</tt>, your working copy has mixed 119revisions. The things you just committed are now at the HEAD 120revision, and everything else is at an older revision.</li> 121 122<li>Certain commits are disallowed: 123 <ul> 124 <li>You cannot commit the deletion of a file or directory which 125 doesn't have a working revision of HEAD.</li> 126 <li>You cannot commit a property change to a directory which 127 doesn't have a working revision of HEAD.</li> 128 </ul> 129</li> 130 131<li><tt>svn update</tt> will bring your entire working copy to one 132 working revision, and is the typical solution to the 133 problems mentioned in point #2.</li> 134</ol> 135 136<p><em>Book reference:</em> <a 137href="http://svnbook.red-bean.com/svnbook/ch02s03.html#svn-ch-2-sect-3.4">The 138 limitation of mixed revisions</a>.</p> 139 140 141<!-- =================================================== --> 142 143<h2>Be patient with large files</h2> 144 145<p>A nice feature of Subversion is that by design, there is no limit 146to the size of files it can handle. Files are sent "streamily" in 147both directions between Subversion client and server, using a small, 148constant amount of memory on each side of the network.</p> 149 150<p>Of course, there are a number of practical issues to consider. 151While there's no need to worry about files in the kilobyte-sized range 152(e.g. typical source-code files), committing larger files can take a 153tremendous amount of both time and space (e.g. files that are dozens 154or hundreds of megabytes large.)</p> 155 156<p>To begin with, remember that your Subversion working copy stores 157pristine copies of all version-controlled files in the 158<tt>.svn/text-base/</tt> area. This means that your working copy 159takes up at least twice as much disk space as the original dataset. 160Beyond that, the Subversion client follows a (currently unadjustable) 161algorithm for committing files:</p> 162 163 <ul> 164 <li>Copies the file to <tt>.svn/tmp/</tt> <em>(can take a while, 165 and temporarily uses extra disk space)</em>)</li> 166 167 <li>Performs a binary diff between the tmpfile and the pristine 168 copy, or between the tmpfile and an empty-file if newly 169 added. <em>(can take a very long time to compute, even 170 though only a small amount of data might ultimately be sent 171 over the network)</em></li> 172 173 <li>Sends the diff to the server, then moves the tmpfile into 174 <tt>.svn/text-base/</tt></li> 175 </ul> 176 177<p>So while there's no theoretical limit to the size of your files, 178you'll need to be aware that very large files may require quite a bit 179of patient waiting while your client chugs away. You can rest 180assured, however, that unlike CVS, your large files won't incapacitate 181the server or affect other users.</p> 182 183<!-- =================================================== --> 184 185<h2>Work around commands that don't understand copies/renames</h2> 186 187<p>When a file or directory is copied or renamed, the Subversion repository 188tracks that history. Unfortunately in Subversion 1.0, the only client 189subcommand which actually takes advantage of this feature is <tt>svn 190log</tt>. A number of other commands (such as <tt>svn diff</tt> and 191<tt>svn cat</tt>) ought to be automatically following rename-history, 192but aren't doing so yet.</p> 193 194<p>In all of these cases, a basic workaround is to use <tt>'svn log 195-v'</tt> to discover the proper path within the older revision.</p> 196 197<p>For example, suppose you copied <tt>/trunk</tt> to 198<tt>/branches/mybranch</tt> in revision 200, and then committed some 199changes to <tt>/branches/mybranch/foo.c</tt> in subsequent revisions. 200Now you'd like to compare revisions 80 and 250 of the file.</p> 201 202<p>If you have a working copy of the branch and run <tt>svn diff 203-r80:250 foo.c</tt>, you'll see an error about 204<tt>/branches/mybranch/foo.c</tt> not existing in revision 80. To 205remedy, you would run <tt>svn log -v</tt> on your branch or file to 206discover that it was named <tt>/trunk/foo.c</tt> prior to revision 200, 207and then compare the two URLs directly:</p> 208 209<pre> 210 $ svn diff http://.../trunk/foo.c@80 \ 211 http://.../branches/mybranch/foo.c@200 212</pre> 213 214 215 216<!-- =================================================== --> 217 218<h2>Know when to create branches</h2> 219 220<p>This is a hotly debated question, and it really depends on the 221culture of your software project. Rather than prescribe a universal 222policy, we'll describe three common ones here.</p> 223 224<h3>The Never-Branch system</h3> 225 226<p>(Often used by nascent projects that don't yet have runnable code.)</p> 227 228<ul> 229<li>Users commit their day-to-day work on <tt>/trunk</tt>.</li> 230<li>Occasionally <tt>/trunk</tt> "breaks" (doesn't compile, or fails 231functional tests) when a user begins to commit a series of complicated 232changes.</li> 233</ul> 234 235<p><em>Pros:</em> Very easy policy to follow. New developers have low 236 barrier to entry. Nobody needs to learn how to branch or merge.</p> 237 238<p><em>Cons:</em> Chaotic development, code could be unstable at any 239 time.</p> 240 241<p>A side note: this sort of development is a bit less risky in 242Subversion than in CVS. Because Subversion commits are atomic, it's 243not possible for a checkout or update to receive a "partial" commit 244while somebody else is in the process of committing.</p> 245 246 247<h3>The Always-Branch system</h3> 248 249<p>(Often used by projects that favor heavy management and supervision.)</p> 250 251<ul> 252<li>Each user creates/works on a private branch for <em>every</em> coding task. 253 </li> 254<li>When coding is complete, someone (original coder, peer, or 255 manager) reviews all private branch changes and merges them to 256 <tt>/trunk</tt>.</li> 257</ul> 258 259<p><em>Pros:</em> <tt>/trunk</tt> is guaranteed to be 260 <em>extremely</em> stable at all times. </p> 261 262<p><em>Cons:</em> Coders are artificially isolated from each other, 263 possibly creating more merge conflicts than necessary. 264 Requires users to do lots of extra merging.</p> 265 266 267<h3>The Branch-When-Needed system</h3> 268 269<p>(This is the system used by the Subversion project.) 270 271<ul> 272<li>Users commit their day-to-day work on <tt>/trunk</tt>.</li> 273 274<li>Rule #1: <tt>/trunk</tt> must compile and pass regression tests at 275all times. Committers who violate this rule are publically 276humiliated.</li> 277 278<li>Rule #2: a single commit (changeset) must not be so large 279so as to discourage peer-review.</li> 280 281<li>Rule #3: if rules #1 and #2 come into conflict (i.e. it's 282impossible to make a series of small commits without disrupting the 283trunk), then the user should create a branch and commit a series of 284smaller changesets there. This allows peer-review without disrupting 285the stability of <tt>/trunk</tt>.</li> 286 287</ul> 288 289<p><em>Pros:</em> <tt>/trunk</tt> is guaranteed to be stable at all 290 times. The hassle of branching/merging is somewhat rare.</p> 291 292<p><em>Cons:</em> Adds a bit of burden to users' daily work: 293 they must compile and test before every commit.</p> 294 295 296<!-- 297 298 299Mapping CVS tasks to SVN tasks 300============================== 301 302This section is just a re-indexing of topics covered in the book, 303for people who prefer to learn from the "bottom up" rather than "top down". 304It shows some common CVS operations, and then the equivalent SVN operation, 305followed by a link to the book which explains more. 306 307 308* Importing data. 309 310* Checking out a working copy. 311 312* Seeing your changes. 313 314* Undoing your changes. 315 316* Resolving a conflict. 317 318* Adding binary files. 319 320* Activating keyword expansion and/or EOL translation. 321 322 323TAGS: 324 325* Creating a tag from a working copy 326 327* Creating a remote tag 328 329* Seeing all of a project's tags 330 331* Comparing two tags 332 333* Seeing the logs between two tags 334 335* Tweaking a tag 336 337 338BRANCHES: 339 340* Creating a branch and switching to it 341 342* Finding the beginning of a branch 343 344* Merging a branch to trunk, or vice versa 345 346--> 347 348 349</body> 350</html> 351