= Managing Application Releases with CVS =
Author: David Garcia Garzon /
Wiki source
Because CVS documentation is so large and sparse, and,
becasue it gives you too much freedom on how you use it,
often is not that easy to choose the suited life cycle
to follow for your CVS project.
This tutorial, first presents a model for project life cycle,
and then, shows how it can be implemented using CVS.
The reader will be guided to create a dummy project example
and perform on it the key steps of such life cycle.
%(toc)s
= The project releases policy =
== Version numbers ==
A distributed team of programmers is going to develop an aplication
named 'theapp'.
They have choosen a 'M.m.r' version numbering schema being:
- Major version number (M):
- Will change when the release implies incompatibility with previous version or an important architectural change.
'theapp 2.4.1' -> 'theapp 3.0.0'
- Minor version number (m):
- Will change when some features have been added but there is no major changes.
'theapp 2.4.1' -> 'theapp 2.5.0'
- Release (minor-minor) version number (r):
- Will change when only bug fixes have been added without adding any user detectable feature.
'theapp 2.4.1' -> 'theapp 2.4.2'
== Kinds of releases ==
The team can do differents kinds of releases for the project:
* A Public release (a.k.a. Official release) is a release that you publicly offer to users and is expected to be supported.
** A Featured release groups all those official releases that shares the same features, that is the 'M.m' part of the release name.
** A Bugfixed release is an official release that has the minor-minor version number different to 0. So only bugfixing have been done from the previous one.
* A Development release (a.k.a. Snapshot) is an unsuported release between two official releases. They are used for:
** being reference points on the development,
** giving advancements to companion applications developers, and,
** alpha and beta testing.
Snapshots are named appending an ISO date and a number
(the snapshot order within the day) to the official release version
that is being developed.
For example, if you are developing towards '2.4.1' and you get an
snapshot of it, it will be named 'theapp 2.4.1 20011124-1'.
Another snapshot the same day will be 'theapp 2.4.1 20011124-2' and so.
== Development progress ==
The features to be reached at the next featured version
(i.e. '2.4.0') are previously specified.
The development team develops towards this millestone.
When those features are reached (or abandoned), 'theapp' is
released as 'theapp 2.4.0' and the the next millestone
(2.5.0 or 3.0.0) starts to be developed.
Once you have started the development of the next featured version (say
2.5.0), you may detect bugs on 2.4.0. You can do the bug fixing
on the 2.4.0 base code and then release that as 2.4.1.
The bug fixing can be done on the 2.4.1 line and then applied back to
2.5.0 line or the reverse process, that is fixing on 2.5.0 and applying
back to 2.4.1. This mechanism will keep the 2.4.0 user bug fixed without
having to wait new featured versions.
== Experimental development ==
Another issue we have to deal are experimental development lines.
Experimental development appears when you are trying to implement
features that you don't know whether it will be part of any official release.
The same mechanism as for the experimental development is used to
develop forward releases.
That is, advancing the development of some features that they will
not be present on the current featured version but in the next one.
For example, you may want to start the implementation
of 3.0.0 features while you are still developing 2.5.0
Rationale: One can think that the better way to manage an experiment
is outside the repository (CVS) control. This is far from true.
By evolving it in a branch you could get the benefits of frequent commits
for change tracking, and it is also easier to make diffs and merges with
the main trunk.
Notice: Experimental branches should have a very short life.
As the code diverges from the main branch, the merge will be harder.
To lighten this you should limit the files or folders under experimentation
and do frequent merges from the main branch to the experimental one.
= An example of CVS implementation =
Now, I am going to guide you on creating a dummy CVS project
and applying to it some of the key steps of the life cycle
explained before.
Let's do the development from one featured version to
another to be the main CVS branch.
We will place CVS tags on snapshots points and create
branches whenever a new featured version is reached.
Bugfixed version will be performed on such branches and
merged back to the main branch if necessary.
Experimental development also takes part on a separated
branch and it can be merged to the main branch anytime.
After the tutorial your cvs repository will get a look similar to this one:
The tutorial suposes that you have already an available
cvs repository
and that you have the CVSROOT environment variable
pointing to it.
It also suposes that you know the basic of CVS usage.
That is:
* creating a working copy,
* performing changes and committing them back,
* updating your working copy to the repository state, and
* solving merging conflicts.
I recommend you to create a directory named 'cvstutorial'
or something like that where to place all the stuff of this tutorial.
Consider that all the paths are relatives to that directory.
== Create a testing module ==
Let's create our dummy project named 'theapp' and
let's add it as a new module named 'mymodule' on the cvs.
Note: It's common to put to the same name for the
module and the application, but because this can be not
your case, we will use different names for you to know which
one we are talking about each time.
The steps are:
* Create a directory named 'initial'
* Create some files and directories inside of it. Those files will be your project content.
* Let one of those files be named 'RELEASE'.
It will contain data about the project progress.
You will simulate development by adding lines to this file.
* Place in the RELEASE file the text: 'Project starting point'
* Assure your shell is placed at the 'initial' directory and import its content as been the 'mymodule' CVS module by executing:
cvs import -m 'MyApp project started' mymodule theapp_main theapp_unreleased
The '-m' option specifies a comment for the CVS action.
If you don't put this option on any CVS command that requires it
a text editor will appear.
Using the editor is more easy for real usage.
Once the repository has been created you can forget about the
initial directory.
== Do some 'development' ==
Now we will start the development of 'theapp 1.0.0'.
* Place your shell at cvstutorial directory
* Create a working copy of the repository:
cvs checkout mymodule
This will create the directory 'mymodule' containing the working copy.
* You'd better to rename the directory 'mymodule' as 'workcopy' to avoid overwritting it when you will do another checkout.
* Modify the 'RELEASE' file in order to get this content:
1.0.0
* First feature
Project starting point
* Now that you have added the first feature, commit the change to the repository.
cvs commit -m 'First feature added'
== Release an snapshot ==
Now that you have implemented the first feature it could be a good
idea to get a development release.
* Place an snapshot tag on the main branch
cvs rtag -Fa theapp_1_0_0_20011124-1 mymodule
Although '-Fa' options are not needed here, I always use
them beause the same command line can be used to move
the tag later if you were wrong placing it here.
* Now, you can add a '* Second feature' line to the RELEASE file, commit it and tag the module status as 'theapp_1_0_0_20011124-2'.
== Issue an official release ==
First of all we will do the 1.0.0 release
* Ensure you have committed all the changes from working copies you want to include in the 1.0.0 release
* Create a tag for the release
cvs rtag -Fa theapp_1_0_0_release mymodule
This will tag all the files in the main branch of your module with the tag 'theapp_1_0_0_release'.
Now, let's prepare the bug fixing branch for 1.0
* Create an sticky tag for the 1.0 bug fixing branch
cvs rtag -Fa -b -r theapp_1_0_0_release theapp_1_0 mymodule
Now you have two branches: the main branch, ready for the development of the 1.1.0 release
and the 1.0 bugfixing branch ready for the development of the 1.0.1 release.
== Fixing a bug on a released version ==
The workcopy is assigned to the main branch so further development
on this working copy aplies to the 1.1.0 development.
If you want to fix a bug for the 1.0.1 version, you must create a new
working copy from the 1.0 branch.
* Checkout a new repository with the 1.0 branch sticky tag.
cvs checkout -r theapp_1_0 mymodule
* Rename this working copy as 'workcopy1.0' and go to this directory.
* Simulate some fixing by adding those lines at the top of the RELEASE file:
1.0.1
* First fix
* Commit these changes
cvs commit -m 'Fix: Something weird fixed'
When you are satisfied with the fixes, then, you can create a tag for the release 1.0.1
cvs rtag -Fa -r theapp_1_0 theapp_1_0_1_release mymodule
Notice: By adding '-r theapp_1_0' you are tagging only the 1.0 branch.
== Merge the fix on the main branch ==
Hint: This exercise will be more interesting if
you perform and commit some development towards 1.1.0 on 'workcopy'.
Now you want to apply the fixes to the main branch.
* Go to the main branch working copy (workcopy)
* Execute the command:
cvs update -j theapp_1_0
This will apply to your working copy all the changes you made on the 1.0 branch from the branching point.
* You'd better tag the 1.0 branch in order to know where the branch was done:
cvs rtag -Fa -r theapp_1_0 theapp_1_0_merged_to_main mymodule
* Remember to commit the merge.
cvs commit -m 'Merged the first fix done for 1.0.1'
== Fixing and merging a second fix ==
Additional fixings on this branch must be merged in a different way.
We will use the tag 'theapp_1_0_merged_to_main' placed on the previous
merging, as a reference point in order to specify which changes must
be applied.
* Make the new fixes on the branched working copy and commit them
* Create a tag for the release 1.0.2 on the branch 1.0
cvs rtag -Fa -r theapp_1_0 theapp_1_0_2_release mymodule
* From the working copy of the main branch ('workcopy') do:
cvs update -j theapp_1_0_merged_to_main -j theapp_1_0
This will apply to your working copy all the changes you made on the branch from the branching time.
* Commit the changes:
cvs commit -m 'Merged fixes done for 1.0.2'
* Move the merging reference to the current state of the branch:
cvs rtag -Fa -r theapp_1_0 theapp_1_0_merged_to_main mymodule
== Backporting fixes from the main branch ==
Often bug fixes are done on the main branch as part of the normal
development, and you want to apply this fixes to an older release.
The easiest way to proceed is to delimitate the changes,
using dates or tags. In that case, you can apply the same
steps used to apply fixes to the main branch but in the
inverse sense, from the main branch to the BugFixed branch.
Just because having delimited changes is not always possible, you
have to deal with patching files separately, using file revision
numbers.
File revisions are very different from application releases.
Revisions are the name of differents commitments for a file.
So dealing with revision you can isolate the changes done between
two commitments of a file.
== Creating an experimental branch ==
TODO
== Exporting tagged releases as source tarballs ==
When you do a development release or an official release,
you may want to offer a tarball containing the project files.
Because a working copy done with a ckeckout has, not only the
project files but also some CVS administration files, is not
a good idea to tarballing from it.
You can use the CVS 'export' subcommand that creates a clean
copy of the project files with a concrete tag.
So for a official release you will do:
cvs -d $CVSROOT export -r theapp_1_0_0_release -dtheapp mymodule
tar cvfz theapp1.1.0-src.tar.gz theapp/*
and for a development relese you will do:
cvs -d $CVSROOT export -r theapp_1_0_0_20020110-1 -dtheapp mymodule
tar cvfz theapp1.1.0-20020110-1-src.tar.gz theapp/*
= Other CVS documentation =
* The official CVS manual:
It provides detailed information about CVS usage.
Most CVS distributions bring it on several formats:
'info' pages, html pages, Windows help file...
It is also available online.
* Basic CVS usage:
It is the tipical quick manual that is provided to developers
that doesn't have to deal with repository management and
project management.
It is available on my web site
as companion of the tutorial you are reading now.
* Step-to-step guide to stablish a CVS system:
It describes the operations related to the CVS repository
creation and administration.
It is available on my web site
as companion of the tutorial you are reading now.
* CVS hints:
It is a list of advanced issues of CVS that could be helpfull.
It is available on my web site
as companion of the tutorial you are reading now.
= Multilingual terms glossary =
The following table is provided to localize the project
management vocabulary used on this tutorial.
It is intended to help giving courses based on this
tutorial but without abusing of english terms when
native terms exists.
I will be glad to receive additions, corrections and
translations to your own languages.
| English | Spanish | Catalan | Your Language Here |
| Repository | Repositorio | Repositori | ? |
| Sandbox | Copia de trabajo | Còpia de treball | ? |
| Millestone | Hito | Fita | ? |
| Release | Entrega | Entrega | ? |
| Version | Versión | Versió | ? |
| Branch | Rama | Branca | ? |
| Tag | Marca | Marca | ? |
| Policy | Política | Política | ? |
| Team | Equipo | Equip | ? |
| Life cycle | Ciclo de vida | Cicle de vida | ? |
| Feature | Característica, Funcionalidad | Característica, Funcionalitat | ? |
| Bug | Fallo | Falla | ? |
| Fix | Corrección | Correcció | ? |
| Merge | Fusión | Fusió | ? |
| Develop | Desarrollar | Desenvolupar | ? |
| Snapshot | Instantánea | Instantània | ? |
| Path | Ruta, Localización | Camí, Localització | ? |
| Commit | Confirmar | Confirmar | ? |
| Update | Actualizar | Actualitzar | ? |
| Checkout | Crear copia de trabajo | Crear còpia de treball | ? |