Subversion
Introduction
Subversion (called also SVN) is the source control system used at Openbravo ERP and Openbravo POS projects. SVN provides the means to store not only the current version of a piece of source code, but a record of all changes (and who made those changes) that have occurred to that source code. Use of SVN is particularly common on projects with multiple developers, since Subversion ensures changes made by one developer are not accidentally removed when another developer posts their changes to the source tree.
Some common Subversion terminology
The following is a list of common terminology used when working with Subversion. Please notice that some of these definitions have been extracted from Revision control Wikipedia article.
- Subversion client Software run by a user to access a Subversion server also called Subversion repository.
- Subversion repository The Subversion server stores a copy of the files of the project. The server retains both the most recent version and every historical version (past changes).
- Trunk Development with Subversion progresses similar to a tree. The main development occurs against the trunk.
- Branch A split of development off of the trunk or another branch. Branches allow developments to diverge either permanently or temporarily.
- Tag A tag or label refers to an important snapshot in time, consistent across many files. These files at that point may all be tagged with a user-friendly, meaningful name or revision number.
- Revision A revision or version is one version in a chain of changes. A versioned file belongs to a particular version.
- Head revision is the last source code revision downloaded to your machine from the source code repository.
- Working copy is the local copy of repository's source code. That is the code a developer works on.
- Check-out A check-out creates a local working copy from the repository. Either a specific revision is specified, or the latest is obtained.
- Update An update merges changes that have been made in the repository (e.g., by other developers) into the local working copy.
- Commit A commit (check-in) occurs when a copy of the changes made to the working copy is written or merged into the repository.
- Revert In order to resolve any conflicted state, revert any file or directory modified locally to a previous revision of it.
- Merge A merge or integration brings together two sets of changes to a file or set of files into an unified revision of that file or files.
- This may happen when one user, working on those files, updates their working copy with changes made, and checked into the repository, by other users. Conversely, this same process may happen in the repository when a user tries to commit their changes.
- It may happen after a set of files has been branched, then a problem that existed before the branching is fixed in one branch and this fix needs merging into the other.
- It may happen after files have been branched, developed independently for a while and then are required to be merged back into a single unified trunk.
- Conflict A conflict occurs when two changes are made by different parties to the same document, and the system is unable to reconcile the changes. A user must resolve the conflict by combining the changes, or by selecting one change in favour of the other.
Subversion services for Openbravo projects
Browsing the source code via web
Though Subversion repositories are most commonly accessed using a special piece of software called a Subversion client, it is also possible to use a web-based interface to view Openbravo repositories.
Commits mailing list
There is mailing list called openbravo-commits. For every commit to the Openbravo ERP repository an email is generated and send to the list showing who made the change, when they made it, what files and directories changed, and how they changed.
Subversion SourceForge mirror
There are read-only mirrors of the Openbravo ERP and Openbravo POS Subversion repositories. Be aware that:
- The SourceForge subversion revision numbers do not match our Subversion server. We always use as reference the revision numbers from our main server (not the mirrored server).
- The localization and installer modules are not replicated
This is due to limitations in the synchronization mechanism and in the SourceForge Subversion server.
User administration
If you have an account at Openbravo Subversion server (provided by Openbravo) you can use the web based administration interface to change your password and to check to which repositories you have written access.
Repository structure for Openbravo projects
Openbravo projects have the following structure:
- project_name
- tags
- trunk
- branches
In Openbravo projects the main development activity occurs in the main development trunk:
- Openbravo ERP development trunk
- Openbravo POS development trunk
All developers commit the changes against this branch. When a version is reach, then is tagged and appears in the tag directories:
If you want to work with a stable version you usually download the tagged version (a released version) and if you want to follow the development you download trunk.
Repository structure for translations
Translation repositories are in:
In each repository (ERP and also POS) there's a language code_country code folder for each translation and inside each folder there's three more folders which replicates the same structure as the development repositories:
- trunk: Here you will find the latest translation for the language code_country code translation.
- branches: When a translation is finalized for a given Openbravo ERP/POS release it should be copied into a folder with the release number as the name. So anyone trying Openbravo ERP/POS will find the translated xml files for that release and language. You must use the release numbers (e.g 2.40) as folder names.
- tags: When a version is packaged and published into SourceForge and is made available to all users, the version is tagged. This allows to track the sources of what has been published. Once a version has been tagged, work can continue in its branch to further improve the translation.
For example the French team could have a tree directory like that looks like:
- fr_FR
- branches
- 2.40
- 2.50
- tags
- 2.40
- 2.50
- trunk
- branches
Note: In each directory is expected to be found the xml files. If you want to keep other file formats (i.e. .po, .zip, ...) create a sub-directory in each folder you want to keep those files, fr_FR/trunk/po for example. |
Working with a Subversion client
Required software
To be able to work with Openbravo's Subversion (SVN) repositories you need a Subversion client compatible with Subversion version 1.5. The following clients are recommended:
- The official SVN 1.5 client, included in most Linux and BSD distributions; available for Linux, BSD, Mac OS X, and Windows:
- If you use Eclipse IDE, you can install Subclipse plug-ins to access Subversion repository:
- TortoiseSVN 1.5 for Microsoft Windows provides a nice and easy user interface for Subversion:
Checking out the sources
To check out the sources for the first time from the repository, use this command:
svn co https://dev.openbravo.com/svn/openbravo/trunk/ openbravo
If you are interested in checking out the Openbravo ERP localization module use:
svn co https://dev.openbravo.com/svn/localization/ localization
If you are interested in checking out a specific version of Openbravo ERP tag, do:
svn co https://dev.openbravo.com/svn/openbravo/tags/r2.35mp1 openbravo
Where r2.35mp1 is the tag to check out.
Updating sources
Every day people make changes to the repository, to get your latest updated sources, use:
svn up
Creating a patch
Patches, sometimes called diffs, describe changes of your local subversion copy when compared to the server showing all the changes that you have introduced.
To create a patch from the current repository, use the following command:
svn diff -u > patch.diff
For example, when you have a bug fix you create a diff to be able to send your fix to other people.
The file patch.diff contains your local changes and can be applied in other systems using the command patch.
Committing changes
Once you get approval to commit to the SVN repository. See how to get SVN write access in our contributor's guide.
To "add" any new files that you created use:
svn add new-file.txt
And then commit your changes to the repository:
svn commit -m"A comment about what have you changed"
Applying revisions to your copy
It is a common situation when you are working with a version of Openbravo and you want to apply a specific revision from trunk that fixes a particular bug.
Imagine that you want to apply revision r1488 from trunk in your local copy.
You can see the changes introduced in revision r1488 using the Openbravo Subversion web interface:
https://dev.openbravo.com/websvn/openbravo/trunk/?rev=1488
You can replace the number 1488 in the given URL by the exact revision number that you want to look.
To apply the changes of that revision you use the following command:
svn merge -r 1487:1488 https://dev.openbravo.com/svn/openbravo/trunk
Sometimes applying a fix directly may fail if the structure of the trees have change a lot. Another way of applying a specific patch is to save it as a patch using the following command:
svn diff -r 1487:1488 https://dev.openbravo.com/svn/openbravo/trunk > patch.diff
you can look at the contents of the file patch.diff. And now you can apply the patch doing:
patch -p0 < patch.diff
Subversion committer's guidelines
Using good commit comments is very important to enhance traceability of changes. When doing a commit to Subversion these are the guidelines for building a proper comment:
- Add a brief but insightful comment about the committed change.
- If the patch was created by someone else, include his name in the comment.
If your commit is related to an issue reported in Mantis, you can benefit from the integration between Subversion and Mantis. Depending on the comment you write for the commit, a note can be automatically added to the issue. Moreover, the status of the issue can be automatically set to 'resolved'.
- Adding a note: To add the commit comment as a note of the issue, you should add to the comment one of the words bug or issue (case insensitive) followed by the number of the issue. In the middle you can put none or more spaces. For example, the following messages would add a note to the issue:
- Issue 107.
- Solves the problem in bug107.
- Solving an issue: To mark the issue as resolved, you should add one of the words fixed or fixes before the text needed to add a note. If we wanted to resolve the issues, the previous examples could be:
- This patch fixes issue 107.
- Solves the login problem. Fixes bug 107.
Take into account that writing issue A and issue B in the same commit message will add comments to both issues. So, for example, solve issue 321, related to issue 223 would add a comment to issues 321 and 223 and solve issue 321. If you want to reference another issue in the same comment, use issue #B instead. In our example: solve issue 321, related to issue #223.
The mailing list commit notifications use the same syntax as the issue tracker to identify the bug ID.
Setting up a local Subversion server
For any reason, someday you need to set up a local Subversion server containing the whole Openbravo source code, a certain folder or a single file.
Follow these simple steps to create in a few minutes your own local version control system accessible to third parties via a local network.
Please notice that this tutorial is made using a Linux folder structure but steps are the same for Windows command line.
- First of all, install Subversion (SVN) version control system client. Take the specific project package for your operating system.
- Make a temporary directory with the repository structure:
mkdir /home/user/repo-tmp mkdir /home/user/repo-tmp/trunk mkdir /home/user/repo-tmp/branches mkdir /home/user/repo-tmp/tags
- Check out Openbravo ERP source code from Openbravo Subversion repository to your temporary trunk folder.
svn co https://dev.openbravo.com/svn/openbravo/trunk/ /home/user/repo-tmp/trunk/
- But, if you want to fill your temporary trunk folder with a single folder...
svn co https://dev.openbravo.com/svn/openbravo/trunk/legal/ /home/user/repo-tmp/trunk/
- ... or a local folder...
cp -Rf /home/user/local-folder/ /home/user/repo-tmp/trunk/
- ... or a local file:
cp /home/user/local-file.txt /home/user/repo-tmp/trunk/
- Create a local Subversion repository (named my-repository) with a project (named my-project):
mkdir /home/user/my-repository cd /home/user/my-repository svnadmin create my-project
- Add files to your local Subversion repository:
svn import -m "Initial fill of my-project" /home/user/repo-tmp/ file:///home/user/my-repository/my-project/
- Make some branches...
svn copy -m "Making a new branch for Jim" file:///home/user/my-repository/my-project/trunk/ file:///home/user/my-repository/my-project/branches/jim-branch/ svn copy -m "Making a new branch for Tom" file:///home/user/my-repository/my-project/trunk/ file:///home/user/my-repository/my-project/branches/tom-branch/
- ... and tags:
svn copy -m "Making a new tag named tag-one" file:///home/user/my-repository/my-project/trunk/ file:///home/user/my-repository/my-project/tags/tag-one/ svn copy -m "Making a new tag named tag-two" file:///home/user/my-repository/my-project/trunk/ file:///home/user/my-repository/my-project/tags/tag-two/
- Configure access to the repository by editing /home/user/my-repository/my-project/conf/svnserve.conf file...
[general] anon-access = read auth-access = write password-db = passwd authz-db = authz
... /home/user/my-repository/my-project/conf/passwd file...
[users] jim = jimpass tom = tompass
... and /home/user/my-repository/my-project/conf/authz file:
[groups] main_developers = jim,tom [/trunk] * = r @main_developers = w [/branches] @main_developers = r [/branches/jim-branch] jim = w [/branches/tom-branch] tom = w [/tags] * = r
- Start your local Subversion server:
svnserve -d -r /home/user/my-repository
- Both you and third parties can now check out the repository...
svn co svn://your-ip/my-project/trunk/ /home/user/trunk-check-out/
- ... commit changes (username and password will be required)...
svn ci -m "Modified a file" /home/user/trunk-check-out/modified-file.txt
- ... and see activity log:
svn log /home/user/trunk-check-out/modified-file.txt
How to manage branches
Highlights
New developments, especially when they are quite big, are recommended not to be done in trunk but in a new branch for the project.
This approach allows isolation between different projects and trunk, preventing the bugs in the core product of an incomplete project.
Please find more information on branching and merging at Chapter 4. Branching and Merging of the Version Control with Subversion free on-line book.
Cycle of a branch life
The two main steps are the branch creation and its merge back. When a new development project is going to be started the first step is to create a branch for it. All the development is done in this project branch, and once the project is finished and tested it is merged back to the trunk.
Additionally to the previously described it is highly recommendable to merge the trunk to the branch once the project is finished and before its complete test, thus, all the modifications in the trunk will be in the project and it will be possible to check if they fit correctly altogether.
If it is going to be a log term project it is preferable not to wait till the project is completed to merge the trunk with it but do regular merges from trunk in order to have latest core modifications within the project and to reduce the possible collisions in the merge back to the trunk.
Management
Example
To explain the branches management let's use the following example:
Creation
A new project is going to be started, starting from the current trunk (revision number 10):
svn cp https://my.svn.repo/trunk https://my.svn.repo/branches/myProject -m "created branch for my project from trunk r10"
This command will create a new branch as a copy of the current trunk and will commit it (r11).
Work in branch
Now it is possible to work in the branch (revisions 14, 15) isolated from the modifications in the trunk (revisions 12, 13, 16)
Merges from trunk to branch
As the modifications in the trunk can fix bugs that may affect to the project or include new functionality and to prevent possible collisions in the future merge back it is a good practice to do regular merges from trunk to project. In this case we want to apply the changes in trunk during the A period of time.
Important note: before merging, please make sure that your working copy is updated and has no commits pending. |
To do this execute in a branch working copy:
svn merge https://my.svn.repo/trunk/
This will update the branch files with the modifications in trunk from revision 12 to 16.
In case any file causes conflicts it will be necessary to manually solve them.
There are two helpful svn commands:
svn status
This will mark with a C all the files with conflicts. It is necessary to edit them and fix the problems, afterwards the file needs to be marked as resolved:
svn resolved myConflictingFile
When all the conflicts have been resolved it is possible to commit the merge. Note that merges are always done in a local working copy and need to be explicitly committed.
svn commit -m "Merge branch with trunk"
This will be the commit r17 in the branch.
Now it is possible to continue the work in branch with the changes in the trunk.
Once the project is finished it is recommendable to merge again the trunk before do the complete testing.
Important note: before merging, please make sure that your working copy is updated and has no commits pending. |
In this case the pending modifications are the ones in the period B:
svn merge https://my.svn.repo/trunk/ .
Resolve conflicts and commit:
svn commit -m "Merge branch with trunk"
Now it might be necessary to do some fixes in the branch to fit it to the new possible stuff from trunk (r24, 26).
Merge back to trunk
Now the project is ready to be merged back to trunk, this will incorporate all the new developments to core product.
This merge should add to trunk all the commits performed in the branch maintaining the ones in the trunk. Thus is not possible to merge from the beginning to the head of the branch because modifications in trunk during periods A and B are already in the branch and would be tried to added again.
The correct way to do this is to compare the trunk as it was when it was merged with branch last time with the branch head and apply this differences in the trunk.
Important note: before merging, please make sure that your working copy is updated and has no commits pending. |
This is done in a trunk working copy:
svn merge --reintegrate https://my.svn.repo/branch .
Once again solve the possible conflicts and commit:
svn ci -m "Merged branch with trunk"
This commit would be the revision number 27.
svnmerge.py
Since currently Openbravo subversion repository is using v1.5 it is no longer needed to use svnmerge, because this version maintains merge tracking |
svnmerge.py is a useful tool to manage branches.
It basically keeps a track of the revision number of the merges. Preventing the user of doing it manually.
Initialization in project branch
Once the project branch has been created and previous to any modification on it svnmerge must be initialized:
svnmerge init
This will modify . file and must be committed:
svn ci -F svnmerge-commit-message.txt
Merge trunk to branch
Now it is possible to know in an easy way the modifications done in trunk and not merged to branch. If we have committed r15 in branch to know what can we merge to branch it is enough to execute this from a branch working copy:
svnmerge avail
It would return:
12-13, 16
which means that revision 12 to 13 and 16 from trunk have not been merged with branch.
To do the merge, type from a branch working copy:
svnmerge merge
And that's all, note that you needn't know the revisions to merge.
Just a tip: be patient, svnmerge does not show any feedback till the merge is completed, depending on the number of differences and on the net it can spend a lot of time looking as it was hung.
Now it is time to resolve conflicts and commit.
Merge back to trunk
To be able to merge a branch to the trunk it must be initialized at any point in the trunk working copy.
svnmerge init https://my.svn.repo/branch/ svn ci -F svnmerge-commit-message.txt
It is possible to know pending changes to be merged with:
svnmerge avail -S branch
And to merge them with:
svnmerge merge --bidirectional -S branch
Noticing or Ignoring Ancestry
Example
Let's define an example.
$cat a.txt This is an example file
$svn add a.txt A a.txt
$svn ci -m "Added a.txt" Sending C_CASH_TRG.xml Adding a.txt Transmitting file data . Committed revision 200.
$svn del a.txt D a.txt
$svn ci -m "deleted a.txt" Deleting a.txt Committed revision 201.
$touch a.txt $edit a.txt $cat a.txt This is (new) an example file
$svn add a.txt A a.txt
$svn ci -m "Added new a.txt" Sending C_CASH_TRG.xml Adding a.txt Transmitting file data . Committed revision 202.
Maintaining customizations in a re-created file
Let's create a new working copy for r200
$svn co https://my.svn.repo/a.txt@200 testing $cd testing $edit a.txt $cat a.txt This is an example file cusomized $svn merge -r200:HEAD https://my.svn.repo . Skipped 'a.txt' C a.txt
For svn merge file a.txt@200 and a.txt@202 are two different objects because they do not share ancestor. So what it is trying to do is to remove if first and then create a new one, and the conflict is raised because it is trying to remove a customized file.
But there is a parameter for svn merge which allows not to take into account ancestors: --ignore-ancestry. This parameter makes merge to work like patch does, this is, taking into account just the file path and name but not ancestry. Thus:
$svn co https://my.svn.repo/a.txt@200 testing2 $cd testing2 $edit a.txt $cat a.txt This is an example file cusomized $svn merge -r200:HEAD --ignore-ancestry https://my.svn.repo . G a.txt $cat a.txt This is (new) an example file cusomized
Here the file has maintained its customizations and merged the new file.
Comparing branches without common ancestors
This is useful in other to perform comparisons between two branches without shared ancestors.
For example, a new branch for a client which was not under CSM with svn import. Now we want to apply the changes in this client to a new working copy. Trying to merge in the typical way:
$svn merge https://my.svn.repo/trunk https://my.svn.repo/branches/newClient . D a.txt A a.txt
It removes all the files in the working copy and adds the ones in the client branch, this is because it does not identify them as the same files but as new ones.
The correct way to do this is:
$svn merge --ignore-ancestry https://my.svn.repo/trunk https://my.svn.repo/branches/newClient . U a.txt
Recommended links
For more general or technical information concerning Subversion, please visit:
- Subversion's Frequently Asked Questions (FAQ).
- Version Control with Subversion free on-line book.
- Source Control How-To by Eric Sink.
- A Visual Guide to Version Control by BetterExplained.com.
- Subversion Merge Tracking – The Basics by Guido Haarmans.
- Subversion 1.5 merge-tracking in a nutshell by Ben Collins-Sussman.
- Merging and branching in Subversion 1.5 by John Ferguson Smart.
Categories: Community | Development | OpenbravoPOS


