{"id":29469,"date":"2022-04-04T09:17:09","date_gmt":"2022-04-04T09:17:09","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=29469"},"modified":"2022-12-23T06:19:50","modified_gmt":"2022-12-23T06:19:50","slug":"subversion-svn-best-practices","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/subversion-svn-best-practices\/","title":{"rendered":"Subversion SVN Best Practices"},"content":{"rendered":"\n<p>This is a quick set of guidelines for making the best use of Subversion in your day-to-day software development work.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use a sane repository layout<\/h2>\n\n\n\n<p>There are many ways to lay out your repository. Because branches and tags are ordinary directories, you&#8217;ll need to account for them in your repository structure.<\/p>\n\n\n\n<p>The Subversion project officially recommends the idea of a &#8220;project root&#8221;, which represents an anchoring point for a project. A &#8220;project root&#8221; contains exactly three subdirectories:&nbsp;\/trunk,&nbsp;\/branches, and&nbsp;\/tags. A repository may contain only one project root, or it may contain a number of them.<\/p>\n\n\n\n<p><em>Book reference:<\/em>&nbsp;<a href=\"http:\/\/svnbook.red-bean.com\/nightly\/en\/svn.reposadmin.planning.html#svn.reposadmin.projects.chooselayout\" target=\"_blank\" rel=\"noopener\">Choosing a Repository Layout<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Commit logical changesets<\/h2>\n\n\n\n<p>When you commit a change to the repository, make sure your change reflects a single purpose: the fixing of a specific bug, the addition of a new feature, or some particular task. Your commit will create a new revision number which can forever be used as a &#8220;name&#8221; for the change. You can mention this revision number in bug databases, or use it as an argument to&nbsp;svn merge&nbsp;should you want to undo the change or port it to another branch.<\/p>\n\n\n\n<p><em>Book reference:<\/em>&nbsp;<a href=\"http:\/\/svnbook.red-bean.com\/nightly\/en\/svn.branchmerge.basicmerging.html#svn.branchmerge.changesets\" target=\"_blank\" rel=\"noopener\">Changesets<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use the issue-tracker wisely<\/h2>\n\n\n\n<p>Try to create as many two-way links between Subversion changesets and your issue-tracking database as possible:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>If possible, refer to a specific issue ID in every commit log message.<\/li><li>When appending information to an issue (to describe progress, or to close the issue) name the revision number(s) responsible for the change.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Track merges manually<\/h2>\n\n\n\n<p><em>### OBSOLETE RECOMMENDATION ###<\/em><\/p>\n\n\n\n<p>When committing the result of a merge, be sure to write a descriptive log message that explains what was merged, something like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Merged revisions 3490:4120 of \/branches\/foobranch to \/trunk.<\/pre>\n\n\n\n<p><em>Book reference:<\/em>&nbsp;<a href=\"http:\/\/svnbook.red-bean.com\/svnbook\/ch04s03.html#svn-ch-4-sect-3.2\" target=\"_blank\" rel=\"noopener\">Tracking merges manually<\/a>, and&nbsp;<a href=\"http:\/\/svnbook.red-bean.com\/svnbook\/ch04s04.html#svn-ch-4-sect-4.1\" target=\"_blank\" rel=\"noopener\">Merging a whole branch to another<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understand mixed-revision working copies<\/h2>\n\n\n\n<p>Your working copy&#8217;s directories and files can be at different &#8220;working&#8221; revisions: this is a deliberate feature which allows you to mix and match older versions of things with newer ones. But there are few facts you must be aware of:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>After every&nbsp;svn commit, your working copy has mixed revisions. The things you just committed are now at the HEAD revision, and everything else is at an older revision.<\/li><li>Certain commits are disallowed:<ul><li>You cannot commit the deletion of a file or directory which doesn&#8217;t have a working revision of HEAD.<\/li><li>You cannot commit a property change to a directory which doesn&#8217;t have a working revision of HEAD.<\/li><\/ul><\/li><li>svn update&nbsp;will bring your entire working copy to one working revision, and is the typical solution to the problems mentioned in point #2.<\/li><\/ol>\n\n\n\n<p><em>Book reference:<\/em>&nbsp;<a href=\"http:\/\/svnbook.red-bean.com\/nightly\/en\/svn.basic.in-action.html#svn.basic.in-action.mixedrevs\" target=\"_blank\" rel=\"noopener\">Mixed-revision working copies<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Be patient with large files<\/h2>\n\n\n\n<p>A nice feature of Subversion is that by design, there is no limit to the size of files it can handle. Files are sent &#8220;streamily&#8221; in both directions between Subversion client and server, using a small, constant amount of memory on each side of the network.<\/p>\n\n\n\n<p>Of course, there are a number of practical issues to consider. While there&#8217;s no need to worry about files in the kilobyte-sized range (e.g. typical source-code files), committing larger files can take a tremendous amount of both time and space (e.g. files that are dozens or hundreds of megabytes large.)<\/p>\n\n\n\n<p>To begin with, remember that your Subversion working copy stores pristine copies of all version-controlled files in the&nbsp;.svn\/text-base\/&nbsp;area. This means that your working copy takes up at least twice as much disk space as the original dataset. Beyond that, the Subversion client follows a (currently unadjustable) algorithm for committing files:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Copies the file to&nbsp;.svn\/tmp\/&nbsp;<em>(can take a while, and temporarily uses extra disk space)<\/em>)<\/li><li>Performs a binary diff between the tmpfile and the pristine copy, or between the tmpfile and an empty-file if newly added.&nbsp;<em>(can take a very long time to compute, even though only a small amount of data might ultimately be sent over the network)<\/em><\/li><li>Sends the diff to the server, then moves the tmpfile into&nbsp;.svn\/text-base\/<\/li><\/ul>\n\n\n\n<p>So while there&#8217;s no theoretical limit to the size of your files, you&#8217;ll need to be aware that very large files may require quite a bit of patient waiting while your client chugs away. You can rest assured, however, that unlike CVS, your large files won&#8217;t incapacitate the server or affect other users.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Know when to create branches<\/h2>\n\n\n\n<p>This is a hotly debated question, and it really depends on the culture of your software project. Rather than prescribe a universal policy, we&#8217;ll describe three common ones here.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Never-Branch system<\/h3>\n\n\n\n<p>(Often used by nascent projects that don&#8217;t yet have runnable code.)<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Users commit their day-to-day work on&nbsp;\/trunk.<\/li><li>Occasionally&nbsp;\/trunk&nbsp;&#8220;breaks&#8221; (doesn&#8217;t compile, or fails functional tests) when a user begins to commit a series of complicated changes.<\/li><\/ul>\n\n\n\n<p><em>Pros:<\/em>&nbsp;Very easy policy to follow. New developers have low barrier to entry. Nobody needs to learn how to branch or merge.<\/p>\n\n\n\n<p><em>Cons:<\/em>&nbsp;Chaotic development, code could be unstable at any time.<\/p>\n\n\n\n<p>A side note: this sort of development is a bit less risky in Subversion than in CVS. Because Subversion commits are atomic, it&#8217;s not possible for a checkout or update to receive a &#8220;partial&#8221; commit while somebody else is in the process of committing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Always-Branch system<\/h3>\n\n\n\n<p>(Often used by projects that favor heavy management and supervision.)<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Each user creates\/works on a private branch for&nbsp;<em>every<\/em>&nbsp;coding task.<\/li><li>When coding is complete, someone (original coder, peer, or manager) reviews all private branch changes and merges them to&nbsp;\/trunk.<\/li><\/ul>\n\n\n\n<p><em>Pros:<\/em>&nbsp;\/trunk&nbsp;is guaranteed to be&nbsp;<em>extremely<\/em>&nbsp;stable at all times.<\/p>\n\n\n\n<p><em>Cons:<\/em>&nbsp;Coders are artificially isolated from each other, possibly creating more merge conflicts than necessary. Requires users to do lots of extra merging.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Branch-When-Needed system<\/h3>\n\n\n\n<p>(This is the system used by the Subversion project.)<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Users commit their day-to-day work on&nbsp;\/trunk.<\/li><li>Rule #1:&nbsp;\/trunk&nbsp;must compile and pass regression tests at all times. Committers who violate this rule are publicly humiliated.<\/li><li>Rule #2: a single commit (changeset) must not be so large so as to discourage peer-review.<\/li><li>Rule #3: if rules #1 and #2 come into conflict (i.e. it&#8217;s impossible to make a series of small commits without disrupting the trunk), then the user should create a branch and commit a series of smaller changesets there. This allows peer-review without disrupting the stability of&nbsp;\/trunk.<\/li><\/ul>\n\n\n\n<p><em>Pros:<\/em>&nbsp;\/trunk&nbsp;is guaranteed to be stable at all times. The hassle of branching\/merging is somewhat rare.<\/p>\n\n\n\n<p><em>Cons:<\/em>&nbsp;Adds a bit of burden to users&#8217; daily work: they must compile and test before every commit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a quick set of guidelines for making the best use of Subversion in your day-to-day software development work. Use a sane repository layout There are many ways to&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-29469","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/29469","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=29469"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/29469\/revisions"}],"predecessor-version":[{"id":29470,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/29469\/revisions\/29470"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=29469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=29469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=29469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}