[plug] Merging 2 files, CVS-style

Peter Wright pete at cygnus.uwa.edu.au
Thu Apr 13 14:26:59 WST 2000


On Thu, Apr 13, 2000 at 12:37:28PM +0800, Nick Bannon offered the
following solution:
> On Thu, Apr 13, 2000 at 11:04:36AM +0800, Peter Wright wrote:
> [...]
> > I'm working on a software project using CVS for version control, which
> > I'm guessing at least a few of you should be familiar with. Now CVS
> > has a very nice conflict-resolution merging facility - when you've
> > changed an old revision of a file and then try to update it, it marks
> [...]
> 
> I think your problem is tricky - the way CVS works is that it has
> _three_ files to compare - two plus a common ancestor. If the
> ancestor and version 1 differ, it'll merge it in. If the ancestor
> and version 2 differ, it'll merge it in. If all three differ, it's a
> conflict.
> 
> Using RCS (which CVS is built on), the following seems to work.
[ snip suggested solution, which does indeed work ]

Thanks very much for that Nick... but....

> Nick.

On Thu, Apr 13, 2000 at 01:43:31PM +0800, Mike Holland explained why
we're going to kick ourselves: 
> On Thu, 13 Apr 2000, Nick Bannon wrote:
> > I think your problem is tricky - the way CVS works is that it has
> > _three_ files to compare - two plus a common ancestor. If the
> > ancestor and
> 
> Quite right, but gee guys ... you'll kick yourselves.
> 
> % man -k merge
> merge (1)            - three-way file merge
[ snip ]
> Does this work? Hope that helps.

*kicks self*

<cartman>Gahddammittt!!!!</cartman>

I'd _just_ finished writing a script implementing Nick's solution above
using the RCS utilities ci, co, rcsmerge. Sigh. :)

Oh well, at least some of it can be salvaged, as the "original" file
still needs to be generated. For those who might be interested, I've
attached both scripts (in perl - yes, would be better done in bourne
shell, I agree) to this mail: the Nick solution is cvsmerge, the
Nick/Mike solution is cvsmerge2.

> Mike Holland  <mike at golden.wattle.id.au>

Thanks to both Nick and Mike for their help.

Pete.
-- 
http://cygnus.uwa.edu.au/~pete/

--
ARTHUR: (as the MAN next to him is squashed by a sheep) Knights!  Run away!
   Midst echoing shouts of "run away" the KNIGHTS retreat to cover with the odd
   cow or goose hitting them still.  The KNIGHTS crouch down under cover.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
-------------- next part --------------
#!/usr/bin/perl -w
# Quick Perl script to automate a CVS-style merge utility as described
# by Nick Bannon <nick at it.net.au>. Relies on the RCS utilities ci, co
# and rcsmerge, plus diff, grep and cut. Probably would be more
# wholesome if done as a shell script. :)

use strict;
# merge file name, should probably make it command-line option
my $merge = ".tmpmerge";

# requires two filename params
if (scalar(@ARGV) != 2) { die "$0 <file1> <file2>\n"; }

my $f1 = $ARGV[0];
my $f2 = $ARGV[1];

# grabs the larger line count of the two files.
my $size = &gtr(&lc($f1), &lc($f2));

system("diff -u$size $f1 $f2 | grep '^ ' | cut -c2- > $merge");
system("ci -t-test $merge ; co -l $merge");
system("cp $f1 $merge");
system("ci -mtest1 $merge;co -l $merge");
system("cp $f2 $merge");
system("rcsmerge -r1.1 -r1.2 $merge");

print "Produced file $merge, removing temporary RCS file $merge,v\n";
unlink("$merge,v");

sub gtr {
	my $a = shift;
	my $b = shift;
	if ($a > $b) {
		return $a;
	} else {
		return $b;
	}
}

sub lc {
	my $file = shift;
	my $out = `wc -l $file`;
	$out =~ m/(\d+)/;
	return $1;
}
-------------- next part --------------
#!/usr/bin/perl -w
# Quick Perl script to automate a CVS-style merge utility as described
# by Nick Bannon <nick at it.net.au>. Relies on the utilities merge,
# diff, grep and cut. Probably would be more wholesome if done as a
# shell script. :)

use strict;
# original file name, should probably make it command-line option
my $orig = ".original";

# requires two filename params
if (scalar(@ARGV) != 2) { die "$0 <file1> <file2>\n"; }

my $f1 = $ARGV[0];
my $f2 = $ARGV[1];

# grabs the larger line count of the two files.
my $size = &gtr(&lc($f1), &lc($f2));

system("diff -u$size $f1 $f2 | grep '^ ' | cut -c2- > $orig");
system("merge $f1 $orig $f2");

sub gtr {
	my $a = shift;
	my $b = shift;
	if ($a > $b) {
		return $a;
	} else {
		return $b;
	}
}

sub lc {
	my $file = shift;
	my $out = `wc -l $file`;
	$out =~ m/(\d+)/;
	return $1;
}


More information about the plug mailing list