# CVS examples

It is not the intention of this document to give a complete introduction to &cvs;. Nevertheless, a few examples should give a quick overview on the basic operations to be performed by the developer.

It is assumed, that the developer is registered with the &app; project and has read/write access to the repository. Also, it is assumed, that the necessary environment variables are setup, so that &cvs; knows how to access the repository. Details about the settings can be found on the SourceForge.net web-site.

Throughout the next sections, the examples given use the &cvs; command line interface. The options are abbreviated. The operations described here are also accessible through various GUI clients available for &cvs;. Also, I usually use the -q (quiet) option to suppress some messages issued by &cvs;. If you omit the -q option, the output differs from the one shown here, even though the result of the operation is the same.

## Checking out from the repository

The very first operation is to fill the sandbox. This is done using the `checkout` operation. The first time the repository is checked-out, it's location must be specified. This is done using the `-d` option. In the example below, you must replace username with your real username at SourcForge.net.

### Filling the sandbox for the first time

      thb:~> cvs -d &cvs-user;@&cvs-host;:&cvs-dir; co &cvs-module;

During the checkout process, &cvs; lists all filenames on the users screen and stores information about the repository's location and all the files checked out in the sandbox. Therefor, you do not need to specify the repository location during following &cvs; operations anymore.

For the &app; project, a directory named `kmymoney` is created in your current working directory.

The above example fills the sandbox with the HEAD revision of all files. This stage is sometimes referred to as the latest-and-greatest and is the latest development stage.

If you plan to keep two or more branches of the project on your machine, please see the chapter Keeping different branches on the same machine for details.

If for some reason, you need to checkout a version of the project that is different from the development stage (e.g. you want to fix a bug in a stable version), you can fill an empty sandbox by supplying the version-tag as parameter to the checkout command.

### Filling the sandbox for the first time with a specific version

      thb:~> cvs -d &cvs-user;@&cvs-host;:&cvs-dir; co -r version-tag &cvs-module;

This will store the version labelled with the tag version-tag in your sandbox. In case version-tag is a branch-tag, you are able to modify the files and check-in changes later on. In case, version-tag is a standard tag, checkin operations will be rejected by &cvs;.

As in the previous example, the directory kmymoney is created as the sandbox.

## Checking in to the repository

Once the sandbox is filled, changes to the project will be applied by the developer. As soon as the developer is confident with the changes, he is about to promote these changes to the other developers. He does that by checking the changes back into the repository.

Checking changes back into the repository should start by performing an update procedure as described in the next section. This may seem strange, but updateing your sandbox will transfer changes performed by other developers in the meantime to your sandbox. It is good practice to re-compile the project if you notice that updateing the sandbox changes it's contents. This assures that the project is still compilable when you check-in your changes.

The next step is to identify the changes you really want to promote. This can be performed by the `diff` operation supported by &cvs;.

### Promote changes to the repository

For the following example, I assume a single file that has been changed in the sandbox (~/kmymoney/kmymoney/knewbankdlg.cpp) and that the current directory is ~/kmymoney/kmymoney. Also, it is assumed, that the file README has been updated by another person in the repository. Since the README file has no influence on the compile process, we omit recompiling in this example.

The part of the original file that has been changed is shown here to understand the output of the `cvs diff` command shown below. The beginning of the file is not included here as it is not changed.

    void KNewBankDlg::okClicked()
    {
      if (nameEdit->text().isEmpty()) {
        KMessageBox::information(this, i18n("The institution name field is empty.  Please enter the name."), i18n("Adding New Institution"));
        nameEdit->setFocus();
        return;
      }

      m_name = nameEdit->text();
      m_city = cityEdit->text();
      m_street = streetEdit->text();
      m_postcode = postcodeEdit->text();
      m_telephone = telephoneEdit->text();
      m_managerName = managerEdit->text();
      m_sortCode = sortCodeEdit->text();
      accept();
    }

The changed version of the method is included here.

    void KNewBankDlg::okClicked()
    {
      if (nameEdit->text().isEmpty()) {
        KMessageBox::information(this, i18n("The institution name field is empty.  Please enter the name."), i18n("Adding New Institution"));
        nameEdit->setFocus();

      } else {
        m_name = nameEdit->text();
        m_city = cityEdit->text();
        m_street = streetEdit->text();
        m_postcode = postcodeEdit->text();
        m_telephone = telephoneEdit->text();
        m_managerName = managerEdit->text();
        m_sortCode = sortCodeEdit->text();
        accept();
      }
    }

Now as the file has been changed, the changes should be promoted to the repository. As explained above, the process starts with checking for changes made by other people.

      thb:~> cvs -q upd
      U README
      M knewbankdlg.cpp
      thb:~>

The above shown output has the following meaning: the file `README` is udpated (U) from the repository to the sandbox because it has been changed by someone else in the meantime. The contents of the file in the sandbox will be replaced by the contents of the file in the repository, because it has not been altered in the sandbox. The file `knewbankdlg.cpp` has been modified (M) in the sandbox and needs to be returned to the repository.

As the next step, one should check what has been changed in the file `knewbankdlg.cpp`. This is done using the following command:

      thb:~> cvs -q diff knewbankdlg.cpp
      74,75d73
      <     return;
      <   }
      77,84c75,84
      <   m_name = nameEdit->text();
      <   m_city = cityEdit->text();
      <   m_street = streetEdit->text();
      <   m_postcode = postcodeEdit->text();
      <   m_telephone = telephoneEdit->text();
      <   m_managerName = managerEdit->text();
      <   m_sortCode = sortCodeEdit->text();
      <   accept();
      ---
      >   } else {
      >     m_name = nameEdit->text();
      >     m_city = cityEdit->text();
      >     m_street = streetEdit->text();
      >     m_postcode = postcodeEdit->text();
      >     m_telephone = telephoneEdit->text();
      >     m_managerName = managerEdit->text();
      >     m_sortCode = sortCodeEdit->text();
      >     accept();
      >   }
      thb:~>

The output shows the changes between the current and the original revision of the file. If this is what needs to be changed then the next step can be started, which is checking the changes back into the repository.

      thb:~> cvs -q ci -m "Avoid return in the middle of a function" knewbankdlg.cpp
      Checking in knewbankdlg.cpp;
      kmymoney/kmymoney/knewbankdlg.cpp,v  <--  knewbankdlg.cpp
      new revision: 1.10; previous revision: 1.9
      done
      thb:~>

If the option -m and the descriptive text is omitted on the command line, &cvs; starts an editor where the developer has to enter a descriptive text about the changes and save that file. Performing checkin operations that way is meaningful, if the description is longer or covers more than one file.

At this point, the changes are stored in the repository. An automatic mail is generated and send to the kmymoney-developer mailing list kmymoney2-developer@lists.sourceforge.net. This mail informs all other developers about your changes and is an indication for them to update their sandboxes. The contents of the mail looks something like this:

      From: Thomas Baumgart <ipwizard@users.sourceforge.net>
      To: kmymoney2-developer@lists.sourceforge.net
      Date: Sat, 24 Nov 2001 12:23:00 -0800
      Subject: [Kmymoney2-developer] CVS update:

      Update of /cvsroot/kmymoney/kmymoney/kmymoney
      In directory usw-pr-cvs1:/tmp/cvs-serv6662

      Modified Files:
               knewbankdlg.cpp
      Log Message:
      Avoid return in the middle of a function
      _______________________________________________
      Kmymoney2-developer mailing list
      Kmymoney2-developer@lists.sourceforge.net
      https://lists.sourceforge.net/lists/listinfo/kmymoney2-developer

While you checkin your changes, you should maintain the file `kmymoney/ChangeLog`. You could probably use the same comments that you use for checkin in your changes or a more general note for many changes. That depends on your changes. Once all your changes are checked in, you also checkin `kmymoney/ChangeLog`.

## Updateing changes performed by other developers

In case you noticed that other developers changed the repository - fortunately you will be noticed by a mail to the developer mailing list if that is the case - you should get those changes to your sandbox. This is accomplished using the `update` command of &cvs;.

### Updating the sandbox

To update the local sandbox the following command is used. As most other &cvs; commands, it operates recursively from the current working directory in the sandbox.

      thb:~> cvs -q upd
      U README
      M knewbankdlg.cpp
      thb:~>

The above shown output has the following meaning: the file `README` is udpated (U) from the repository to the sandbox because it has been changed by someone else in the meantime. The contents of the file in the sandbox will be replaced by the contents of the file in the repository, because it has not been altered in the sandbox. The file `knewbankdlg.cpp` has been modified (M) in the sandbox and needs to be returned to the repository.

If you run the same command again, the output will change, as the file `README` is now up-to-date.

      thb:~> cvs -q upd
      M knewbankdlg.cpp
      thb:~>

Sometimes it is useful to get an overview of what the status of certain files in the repository is without modifying the sandbox (updating). This can be accomplished by using the -n option to the update command.

### Checking the status of files in the sandbox

      thb:~> cvs -nq upd
      U README
      M knewbankdlg.cpp
      thb:~>

The status of the files is the same as explained above, but the file `README` will not be updated. It remains unchanged in the sandbox. If you run this command again, the output remains.

## Dismissing changes

It happens, that a developer tries to modify the source to gain a certain functionality and then wants to discard the changes. This is no problem at all with &cvs;. All the developer needs to do is to remove the file in the sandbox and run the `update` command of &cvs;. This will transfer the original version of the file in question to the sandbox.

Let's assume, that the changes made to `knewbankdlg.cpp` as outlined in a previous chapter should be dismissed. The following commands perform this operation:

### Reverting changes made to the sandbox

      thb:~> cvs -q upd
      M knewbankdlg.cpp
      thb:~> rm knewbankdlg.cpp
      thb:~> cvs -q upd
      U knewbankdlg.cpp
      thb:~> cvs -q upd
      thb:~>

## Keeping different branches on the same machine

Whenever a configuration manager of the project decides to create a new stable release, the developers face a problem: they are not allowed to add new features to the software, only bug-fixes can be checked into the repository. Until the configuration manager opens the sources for further development, the developers are stuck.

To avoid this dilemma, the configuration manager creates a branch off the main development line when he creates the new stable release. Fixes will be made to the release-branch, new developments will be made to the main branch. This eliminates two problems: the configuration manager does not have to lock the current stage and the developers can continue with the implementation of features planned for the next release. Nevertheless, the stable version can be changed (fixes can be applied) and those fixes can be transferred to the main development branch so that they do not show up in future releases of the software.

Since in our project the developers will work on both, bug fixes and new development at the same time, it is convenient to have two sandboxes on the development machine. For the following examples, I have two subdirectories in my $HOME for the project. One is for the release and the other for the develepment branch. I name them `stable` for the release branch and `devel` for the development branch.

`The development branch`

The development branch is the same as you use it today. Just move it from it's current location to $HOME/devel. I kept it directly in my $HOME directory so I did it as follows:

### Keeping stable and development branch on one machine

      thb:~> md devel
      thb:~> md stable
      thb:~> mv kmymoney devel
      thb:~>

Now the development sources are found in ~/devel/kmymoney/. It is important to move all the CVS directories as well. If you start from scratch, then you just follow the instructions on how to checkout the project and do that in the `devel` subdirectory. See the chapter Checking out from the repository for an example.

`The release branch`

As soon as a release branch has been created by the configuration manager, you should get it to the stable directory. You do this by checking it out with the tag that has been assigned. The conventions have been defined in the chapter about Version management. For this example, I assume that a release branch for version 0.4 exists in the repository.

Guess when I wrote this chapter ;-)

### Checking out the stable branch for the first time

      thb:~> cd stable
      thb:~/stable> cvs -d &cvs-user;@&cvs-host;:&cvs-dir; \
    The back-slash is inserted here to break the line for readability. For real usage, the command has to be entered on a single line.
                    co -r rel-0-4-branch &cvs-module;
      thb:~/stable>

At this point it is important to use the branch-tag to be able to modifiy the files and check them back into the repository. If you are in the subdirectory containing the release-branch and you perform a `cvs update`, you will only get those changes, that were made on the branch. Also, changes are checked back into the release branch and do NOT show up on the development branch.

If you want to keep more than one stable branch on your development machine, you can add the version number to the stable directory (e.g. stable-0.4, etc.)

## Promoting bug-fixes to the main branch

Usually, changes made to the release-branch fix a problem. In many cases the problem still exists in the development branch. Therefor, it is necessary to promote the changes made on the release branch back to the development branch.

In most cases, it is very easy to promote the changes. The developer must be very careful though, as the fix might not be applicable in it's form to the development branch anymore as things might have changed drastically due to new features. This is one of the reasons, why I suggest to apply the fix to the release branch and promote it to the developer branch, as the fix as it works on the release branch might break things and broken software is definitly something we do not want to happen on the stable branch.

In this example, I assume changes were made to the single file README. Fortunately, the error found was a documentation problem ;-)

A complex fix could cover many files. The procedure described in the following is then required for each of them seperately. Further on, I assume that the change has been checked in and that the revision was 1.14.2.1 before the fix and is now 1.14.2.2.

### Promoting a change from the release to the development branch

      thb:~> cd devel/kmymoney
      thb:~/devel/kmymoney> cvs -q upd -j 1.14.2.1 -j 1.14.2.2 README
      thb:~/devel/kmymoney> vi README
      thb:~/devel/kmymoney> cvs ci -m "Included fix #493920" README
      thb:~/devel/kmymoney>

First, I go into the devel directory. Then I promote the changes to the README file in the development branch from the repository, verify the changes made (and possibly correct them) and checkin the changes to the development branch. That's it! Of course, a fix to a source code file would be followed by a visual inspection (that's where `vi` or `kdevelop` come into play) and a compile run with further testing before the change is checked back into the repository.

It's important to perform this procedure for every file affected by the fix seperatly, as the revision numbers usually differ significantly between the files. Also, I suggest to fix each problem seperately. This reduces further problems while promoting the changes back to the development branch (e.g. one can leave out a fix completely if it does not apply at all to the development branch).

If the fix is very simple, it can certainly be promoted manually to the development directory tree by merely re-typing it.

## Creating a new stable release

The procedure that needs to be followed is defined in a previous chapter. On the first glimpse, it seems rather complecated but it is not.

If you follow the procedure as it has been defined, you will understand the commands in our example. I assume to have a current unstable version of 0.3.x which will result in the stable version 0.4 and the next development version of 0.5.x. Further on, I assume, that I already differentiate between development and release directories. Also, the version number maintained with KDevelop is setup correctly (0.4.pre1) and all files are checked into the repository.

### Creating a new stable branch

      thb:~> cd devel/kmymoney
      thb:~/devel/kmymoney> cvs tag rel-0-4-pre1
      thb:~/devel/kmymoney> cvs tag -b rel-0-4-branch

      Now modify the version number in KDevelop to 0.5.0, regenerate the files and
      checkin the changes as usual.

      thb:~/devel/kmymoney> cvs tag rel-0-5-base
      thb:~/devel/kmymoney>

Because I know, that I will need the branch sooner or later to fix some problems, I continue to check it out into the stable directory. See Keeping different branches on the same machine for details.