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