Some Merge Info

Merging results from wanting to make changes in one copy of information stored in a CVS repository, and then propogate those changes into a different (but similar) copy.

Start with an illustration of the state of branches within the CVS tree of information. What is shown as the trunk may also just be a branch. For purposes of this document, they are the same thing, but it is nice to have separate names when referring to these two branches.

The goal is to update the trunk with changes made on the branch. The terminology we use is that the trunk is where we are merging-TO, and the branch is where we are merging-FROM.

The cvs command that does all this work is update. The cvs update command makes the changes on the current working directory. Therefore, we check out a fresh copy of the trunk (merge-TO directories), and issue the cvs update command in this merge-TO directory. The update causes changes to the files in this directory, and we check and commit these changes within this merge-TO directory to the trunk.

If we only wanted to do this once, then the process would be very simple. In practice, both the trunk and the branch have further changes made to them (individually), and we want the further changes made to the branch to be merged into (propagated to) the trunk. Fortunately, CVS allows us to tag any branch, such that there is an identification of exactly what is in the branch at a specific point in time. This is illustrated as a dot in the diagram. Branches also have names that are tags. The diagram contains sample names for these tags. If the FROM branch is checked out (from CVS), and immediately tagged, it appears as

If this is the first time that a merge takes place from this branch to this trunk, then the CVS command uses a single -j argument, implying that the changes made on the branch to be merged into the trunk are everything from the time when the branch was created.

In order for CVS to correctly handle files in the branch that may have been added or removed, the -j argument uses the branch tag (instead of tag1).

This command would be

     cvs update -j V6_6-branch

As the branch changes, and we again wish to merge these new changes into the trunk, we need a way of identifying exactly which changes are to be merged. We use the tag assigned during the previous (or first) merge as the beginning point of changes to to be merged in, and we add a new tag to the branch that may be used as the beginning point in a subsequent merge.

What we want in our second merge is to get only those changes that have been made since we first tagged the branch with tag1, also correctly dealing with any files that have been added or removed. The CVS command to do this (correctly) will be

     cvs update -j tag1 -j V6_6-branch
Note that the ordering of these -j arguments is important. The first one marks the beginning point, and the second one marks the end point.

Illustrated, we get the changes identified with a dotted line.

Just to be sure that this process is clear, yet another merge following this second one uses the command

     cvs update -j tag2 -j V6_6-branch
and has a diagram that appears as

Note that a tag3 has appeared, and would be used in a subsequent merge as its beginning point.

There are a couple of ways that this merge process could go wrong. One problem would be if we did not tag the branch just before it is merged into the trunk. This is not a problem the first time we merge, as we use the branch name, instead of a tag in the cvs update command. However, when we want to merge subsequent changes, we will have a problem. CVS will want to merge in all changes since branch creation, thereby doing the initial set over again. This creates conflicts in the merge.