Old Branching Strategy

DEPRECATED

Since moving from svn to git, this document is deprecated in favor of Mifos Version Control Guide.

For historical purposes, outdated content follows.

Branching and Subversion

Branching is very straightforward in subversion, but merging is not. Be sure to follow these guidelines to assure consistent and safe branches and merges.

Merge Tracking and Subversion

What's Missing?

The first merge to/from a branch is pretty easy since the start of the branch is a convenient revision boundary. However, Subversion does not track mergepoints, so it is necessary to manually derive previous mergepoints when performing subsequent merges.

Something That Works

The current strategy is to use Svnmerge to perform merge tracking. Once the Mifos Subversion repository server is upgraded to version 1.5 or later, using Svnmerge will no longer be necessary.

Please download and use the "svnmerge.py trunk version".

HOWTO

Development

Development branches are typically created to fix a specific bug or add a new feature without affecting mainline development.

Creating a Development Branch

When branching the Mifos source code, always branch the entire trunk and always copy to a directory in the branches directory.

Initialize Svnmerge by executing svnmerge init in the branch directory as mentioned in the Svnmerge manual (this should only be done once).

It's fine to check broken code, TODOs, etc. into your branch. That's your sandbox, do what you will. Only when you want us to merge to the trunk do you need to make sure that the patch (collection of changes to be merged) is vetted

Naming Convention

  • If the branch is related to an issue, the name of the branch should be issue_XXXX, where XXXX is the issue number. Example: issue_1339.
  • If the branch has no associated issue but does have a story in Mingle, story_XXXX.
  • If the branch spans multiple issues, a branch name should be discussed and agreed upon via IRC and/or the developer listserv

Merges to the Development Branch

If you are working on a development branch, you're responsible for merging in trunk changes frequently. We recommend merging before starting work each day. If you notice a commit on the trunk that may conflict with your work, merge sooner rather than later!

Execute svnmerge merge in the branch directory as mentioned in the Svnmerge manual.

Here's a brief walkthrough:

  1. Clean up your working copy. That means commit any modified/added/deleted files or directories.
  2. Perform an SVN update to make sure your branch is up to date.
  3. Execute svnmerge merge (optionally including a -r argument to cherry-pick particular changes).
  4. Resolve any merge conflicts as per standard SVN practice (but also see Routine conflicts if merging multiple revisions).
  5. Execute svn commit -F svnmerge-commit-message.txt. The commit may be performed from within a SVN GUI frontend like Subclipse or TortoiseSVN, just make sure you use the exact contents of svnmerge-commit-message.txt as your commit log message.
  6. Remove svnmerge-commit-message.txt.

This whole procedure should be one changeset. Don't change any files or directories in the working copy between the "merge" and "commit" steps except to resolve conflicts. Do not edit svnmerge-commit-message.txt.

Merges back to trunk

Notifying trunk maintainers

Developers working on branches are responsible for proactively notifying trunk maintainers when their changes are ready to be merged to the trunk.

When you are ready for your branch to be merged back into the trunk (ie: every changeset on your branch that hasn't already been merged to the trunk) just cut and paste the phrase:

Please merge all branch changes onto the trunk.

in your commit log message. If you want only a particular revision merged into the trunk, use:

Please merge this revision onto the trunk.

If you know that a particular change should never be merged into the trunk:

Please block this revision from merging onto the trunk.

It would be best if these phrases were on a line by themselves. If you mess up a commit log message, no problem, just give us explicit merge or block instructions on IRC or the mifos-developer mailing list. But if we do use the above procedure for communicating, we'll be encouraged to follow commit emails/feeds closely and can even use scripts to watch for these phrases.

The criteria in VettingPatches must be met prior to submitting a merge request.

Walkthrough

  1. Start with a clean trunk working copy updated to HEAD
  2. svnmerge init BRANCH_URL (this should only be done once)
  3. svn commit -F svnmerge-commit-message.txt && rm svnmerge-commit-message.txt
  4. svnmerge merge -S branches/BRANCH_NAME
  5. svn commit -F svnmerge-commit-message.txt && rm svnmerge-commit-message.txt

Releases

Release branches are created to be able to support particularly important patches (security fixes, etc.) from mainline development, while ignoring others.

Creating a Release Branch

Follow steps for creating a development branch

Naming Convention

  • branches/v1.1.x. This branch would be created so, for example, version 1.2 work could commence on the trunk.

Merges to the Release Branch

Follow steps for performing a development merge, cherry picking and blocking as necessary according to the Svnmerge manual.

Merges back to trunk

Changesets on release branches are generally not merged back to the trunk. However, it is possible to follow steps for performing a development merge back to the trunk.

Tagging

Because of the nature of global revision numbers in Subversion, tags are not necessary. However, it can be convenient to create tags in order to provide a friendlier name.

Ad-hoc tags should be created sparingly.

Release tag example: for the version 1.2.1 release, branches/v1.2.x would be tagged at tags/v1.2.1.

Release Branch Example: Mifos Version 1.1

The branch/merge plan for version 1.1 will serve as a practical example of how to manage a release branch. This plan is largely adopted from "Release Branches" in Producing Open Source Software (Fogel, O'Reilly Media, 2007).

Stabilizing the Release Branch

Release branch example:

https://mifos.svn.sourceforge.net/svnroot/mifos/branches/v1.1.x

This allows work on the next release (probably v1.2.x) to continue on the trunk.

The branch is stabilized by applying only isolated bugfixes and security updates. If possible, a given fix will first be applied to the trunk, then merged to the branch. If the trunk and the v1.1.x branch diverge to the point where this is not possible, the fix will be committed directly to the branch, then manually ported to the trunk if necessary.

Mifos version 1.1 is simply a particular revision of the v1.1.x branch that has been tested and agreed to be the revision to be built from and released. Once this revision is known, it is tagged at:

https://mifos.svn.sourceforge.net/svnroot/mifos/tags/v1.1.0


The release package is built from this tag. Subsequent point releases (if any) are named 1.1.1, 1.1.2, etc. and tagged similarly.

Note that version "1.1" exists in the repository as "1.1.0".

Branch Lifetime

The example v1.1.x branch will be maintained with bugfixes and security updates until a v1.2.x branch is created.

Troubleshooting

Working copy out of date

When trying to commit a merge, you may see an error like this:

svn: Commit failed (details follow):
svn: Your file or directory '.' is probably out-of-date
svn: The version resource does not correspond to the resource within the transaction.
Either the requested version resource is out of date (needs to be updated), or the
requested version resource is newer than the transaction root (restart the commit).

Try performing an "svn update", then run the commit again. If no conflicts are found after the update, the commit should then succeed.

Inconsistent line endings

Merges using Subversion and svnmerge.py are fragile and require all files in a changeset to have consistent line endings on the merge source and target. Please see the developer setup page for details on how to make sure that all text files added to version control always have proper line endings.

If Subversion wasn't set to manage line endings for a particular file, a merge may fail, giving the following message:

svn: File '/tmp/tmp' has inconsistent newlines
svn: Inconsistent line ending style
svn: Error reading spooled REPORT request response

This was from a version 1.5.x SVN client. Using a version 1.4.x SVN client, you may see a message like:

svn: File 'mifos/src/test/java/org/mifos/application/accounts/loan/business/LoanTestUtils.java'
has inconsistent newlines
svn: Inconsistent line ending style

To fix this problem for .java files on a machine with UNIX line-endings, you may have success with something like this:

find . -type f -name '*.java' | xargs awk '/\015/ {print FILENAME}' | sort | uniq | xargs dos2unix

or if your version of grep supports Perl-compatible regular expressions:

find . -type f -name '*.java' | xargs grep -HlP '\r' | xargs dos2unix

I've had more success performing merges when a v1.4.x client is used - Adam M

Erroneous directory property conflict

Svnmerge sometimes detects a property conflict on the top-level directory of the working copy after merging. The following will appear in the output:

# ("C" should be in 2nd column)
 C   .

A "dir_conflicts.prej" will be present, indicating that Svnmerge caused a property conflict while maintaining its internal tracking properties. Workaround:

svn resolved .

Routine conflicts

If svnmerge causes a conflict when merging in multiple revisions, it may be necessary to break up the merge into multiple merges.

What seems to happen is that once a conflict happens, subsequent merges cannot occur on the conflicted file.

For example, say I want to merge changes 127 and 130 from trunk to branches/foo, using:

svnmerge -S trunk -r 127,130

If merging in revision 127 causes a conflict, 130 may not be merged in properly. I would instead have to do something like the following:

svnmerge -S trunk -r 127
# resolve conflicts...
svn commit -F svnmerge-commit-message.txt && rm svnmerge-commit-message.txt
svnmerge -S trunk -r 130
svn commit -F svnmerge-commit-message.txt && rm svnmerge-commit-message.txt