info-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Merging in CVS


From: Kaz Kylheku
Subject: Re: Merging in CVS
Date: 26 Nov 2002 16:49:24 -0800

"Paul D. Smith" <address@hidden> wrote in message news:<address@hidden>...
> %% "Daniels, Dave F [PCS]" <address@hidden> writes:
> 
>   ddf> From my experience, technically the way CVS performs merges is
>   ddf> fine.
> 
> I hope everyone realizes that there _IS_ a significant advantage to the
> way ClearCase handles merges, over CVS: however, as described here, it
> has nothing to do with the interactive merging itself; that's a minor
> thing.
> 
> ClearCase remembers all the merges you have performed (on a per file
> basis) and this allows it to knowledgeably choose closer BASE versions
> during three-way merges.  This makes a _very material difference_ the
> quality and experience of performing ongoing merges between branches in
> ClearCase.
> 
> In CVS, you can emulate what ClearCase does but it requires a lot of
> work... it's virtually impossible to do it by hand.  Essentially you'll
> have to add a label to the FROM version of each file that is merged
> every time you do a merge between branches, then remember the different
> labels and have a way of deciding which one is the right one, then you
> can invoke CVS merge commands specifying that version as the base of the
> 3-way merge.  You'll undoubtedly have to write a tool to manage this if
> you want to get anywhere close to the same level of functionality as
> ClearCase.
> 
> 
> You might consider looking at Meta-CVS; I haven't ever used it, and
> there are no technical docs about how it's implemented on the home page
> so I can't say anything about that, but from the features section of the
> home page it seems pretty cool.

The merge tracking in Meta-CVS is done by automating a certain logical
procedure involving CVS tags; it's a technique which I used to perform
manually. Its advantage is that it does not pollute the repository
with too many tags, and it requires only one global tagging operation
per merge!

A merge sequence is tracked with two tags, call them ``zero'' and
``one''. Both the source and target branch names are encoded into
these tags. The merge operations alternate between these two tags; one
merge will ``rtag -F'' using the zero tag. The next merge will use the
one tag. Then the zero tag, and so forth.

But it's critical to remember which tag to use! When I did this
manually, I would look into the CVS history to find out which tag I
used last, and push the opposite one forward, then merge from the last
one to the opposite.

In Meta-CVS, a clever trick is used. The tag which was last used is
the one which is first in the tag list of a well-known file. And that
well-known file is MAP; every Meta-CVS project has that file.

When CVS deposits a brand new tag into an RCS file, it places it at
the top of the list. And that priority can be used to encode a one-bit
property associated with a pair of tags, such as which one of two tags
is more recent. When you update an existing tag, however, it does not
move to the top of the list! So you must delete the tag, and then
re-create it, if you want it to jump to the top.

So before the global tagging operation, what Meta-CVS does is perform
an untagging operation on the MAP file. So after the global tagging,
it is ensured that the new tag is at the top of the list in that file,
and therefore the next time we know it's *not* the one to push forward
with rtag -F.

Unfortunately, tagging operations are unreliable. We would want a
sequence of these tagging operations to be atomic, but alas, even a
single tagging operation is not.

Clueless people like to complain about the lack of atomic commits in
the CVS platform; but these are hardly a problem at all! The real
problem is the lack of atomic tagging, which is needed to correctly
support higher-level merge operations and such.

Another problem is that if two people concurrently perform the same
merge (from the same source to the same target) that is an open race
condition. The solution is not to do that, but this might be wishful
thinking. Because merging in CVS is hard, it's likely that it's done
rarely and by a dedicated person (i.e. the only one without a
sufficient life who has time to figure it all out). But if you make it
easy enough, non-experts will do it casually, and so the concurrency
problem could arise.

If you can squint your eyes at the atomicity and concurrency issues,
the software is pretty darn convenient. You just type ``mcvs merge
<branch-name>'' and it's done. Check, fix, commit.   If a merge goes
sour and you have to throw away your local edits, you can re-do it
using ``mcvs remerge <branch-name>''.

I maintain two streams of the Meta-CVS sources now. Merging is so darn
convenient that I do it for every single commit. Commit in the branch,
switch to a sandbox that is on the trunk, ``mcvs merge
mcvs-1-0-branch'', inspect, commit.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]