Codingstyle
Version 1 (Jaime Phillips, 01/03/2012 07:58 pm)
| 1 | 1 | Jaime Phillips | h1. Branch Policy |
|---|---|---|---|
| 2 | 1 | Jaime Phillips | |
| 3 | 1 | Jaime Phillips | Our branch policy is based on common practice documented in "the subversion book":http://svnbook.red-bean.com/ pages 113,114. I've copy/pasted from the book, with only slight alterations. Other subversion information can be found on "the subversion website.":http://subversion.apache.org/ |
| 4 | 1 | Jaime Phillips | |
| 5 | 1 | Jaime Phillips | h2. Release Branches |
| 6 | 1 | Jaime Phillips | |
| 7 | 1 | Jaime Phillips | Most software has a typical life cycle: code, test, release, repeat. There are two problems with this process. First, developers need to keep writing new features while quality assurance teams take time to test supposedly stable versions of the software. New work cannot halt while the software is tested. Second, the team almost always needs to support older, released versions of software; if a bug is discovered in the latest code, it most likely exists in released versions as well, and customers will want to get that bug fix without having to wait for a major new release. |
| 8 | 1 | Jaime Phillips | |
| 9 | 1 | Jaime Phillips | Here's where version control can help. The typical procedure looks like this: |
| 10 | 1 | Jaime Phillips | |
| 11 | 1 | Jaime Phillips | # Developers commit all new work to the trunk. Day-to-day changes are committed to / trunk: new features, bug fixes, and so on. |
| 12 | 1 | Jaime Phillips | # The trunk is copied to a “release” branch. When the team thinks the software is ready for release (say, a 1.0 release), /trunk might be copied to /branches/1.0. |
| 13 | 1 | Jaime Phillips | # Teams continue to work in parallel. One team begins rigorous testing of the release branch, while another team continues new work (say, for version 2.0) on /trunk. If bugs are discovered in either location, fixes are ported back and forth as necessary. At some point, however, even that process stops. The branch is “frozen” for final testing right before a release. |
| 14 | 1 | Jaime Phillips | # The branch is tagged and released. When testing is complete, /branches/1.0 is copied to /tags/1.0.0 as a reference snapshot. The tag is packaged and released to customers. |
| 15 | 1 | Jaime Phillips | # The branch is maintained over time. While work continues on /trunk for version 2.0, bug fixes continue to be ported from /trunk to /branches/1.0. When enough bug fixes have accumulated, management may decide to do a 1.0.1 release: / branches/1.0 is copied to /tags/1.0.1, and the tag is packaged and released. |
| 16 | 1 | Jaime Phillips | |
| 17 | 1 | Jaime Phillips | This entire process repeats as the software matures: when the 2.0 work is complete, a new 2.0 release branch is created, tested, tagged, and eventually released. After some years, the repository ends up with a number of release branches in “maintenance” mode, and a number of tags representing final shipped versions. |
| 18 | 1 | Jaime Phillips | |
| 19 | 1 | Jaime Phillips | |
| 20 | 1 | Jaime Phillips | h2. Feature Branches |
| 21 | 1 | Jaime Phillips | |
| 22 | 1 | Jaime Phillips | A feature branch is the sort of branch that's been the dominant example in this chapter (the one you've been working on while Sally continues to work on /trunk). It's a temporary branch created to work on a complex change without interfering with the stability of / trunk. Unlike release branches (which may need to be supported forever), feature branches are born, used for a while, merged back to the trunk, and then ultimately deleted. They have a finite span of usefulness. |
| 23 | 1 | Jaime Phillips | |
| 24 | 1 | Jaime Phillips | Again, project policies vary widely concerning exactly when it's appropriate to create a feature branch. Some projects never use feature branches at all: commits to /trunk are a free-for-all. The advantage to this system is that it's simple—nobody needs to learn about branching or merging. The disadvantage is that the trunk code is often unstable or unusable. Other projects use branches to an extreme: no change is ever committed to the trunk directly. Even the most trivial changes are created on a short-lived branch, carefully re- viewed, and merged to the trunk. Then the branch is deleted. This system guarantees an exceptionally stable and usable trunk at all times, but at the cost of tremendous process overhead. |
| 25 | 1 | Jaime Phillips | |
| 26 | 1 | Jaime Phillips | Most projects (including FOSSology) take a middle-of-the-road approach. They commonly insist that /trunk compile and pass regression tests at all times. A feature branch is required only when a change requires a large number of destabilizing commits. A good rule of thumb is to ask this question: if the developer worked for days in isolation and then committed the large change all at once (so that /trunk were never destabilized), would it be too large a change to review? If the answer to that question is “yes,” the change should be developed on a feature branch. As the developer commits incremental changes to the branch, they can be easily reviewed by peers. |
| 27 | 1 | Jaime Phillips | |
| 28 | 1 | Jaime Phillips | Finally, there's the issue of how to best keep a feature branch in “sync” with the trunk as work progresses. As we mentioned earlier, there's a great risk to working on a branch for weeks or months; trunk changes may continue to pour in, to the point where the two lines of development differ so greatly that it may become a nightmare trying to merge the branch back to the trunk. |
| 29 | 1 | Jaime Phillips | |
| 30 | 1 | Jaime Phillips | 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. |
| 31 | 1 | Jaime Phillips | |
| 32 | 1 | Jaime Phillips | At some point, you'll be ready to merge the “synchronized” feature branch back to the trunk. To do this, begin by doing a final merge of the latest trunk changes to the branch. When that's done, the latest versions of branch and trunk will be absolutely identical except for your branch changes. You would then merge back with the --reintegrate option: |
| 33 | 1 | Jaime Phillips | |
| 34 | 1 | Jaime Phillips | <pre> |
| 35 | 1 | Jaime Phillips | $ cd trunk-working-copy |
| 36 | 1 | Jaime Phillips | $ svn update At revision 1910. |
| 37 | 1 | Jaime Phillips | $ svn merge --reintegrate http://svn.example.com/repos/calc/branches/mybranch |
| 38 | 1 | Jaime Phillips | --- Merging differences between repository URLs into '.': |
| 39 | 1 | Jaime Phillips | U real.c |
| 40 | 1 | Jaime Phillips | U integer.c |
| 41 | 1 | Jaime Phillips | A newdirectory |
| 42 | 1 | Jaime Phillips | A newdirectory/newfile |
| 43 | 1 | Jaime Phillips | U. ... |
| 44 | 1 | Jaime Phillips | </pre> |
| 45 | 1 | Jaime Phillips | |
| 46 | 1 | Jaime Phillips | Another way of thinking about this pattern is that your weekly sync of trunk to branch is analogous to running svn update in a working copy, while the final merge step is analogous to running svn commit from a working copy. After all, what else is a working copy but a very shallow private branch? It's a branch that's capable of storing only one change at a time. |