Resolving Mass Conflicts

I am using CVS and after the merge I have hundreds of conflicts. None of the conflicts are an issue (these are minor changes as a result of differences in keyword expansion on trunk and branch).

I know there were no changes to the files as this is just a merge of the vendor branch into the trunk. Several dozen files were randomly checked to confirm this.

Is there a quick way to resolve all conflicts without doing each one manually? (I have TortoiseCVS, WinCVS and command line).

0


a source to share


4 answers


I'm going to answer my own question as the EMACS solution suggested by @jesup was impractical for anyone who hasn't used EMACS in 15 years!

In my case, because I knew the only conflict was in the $ LOG $ keyword expansion, and I didn't really care about the content of the comments. I saw two possible solutions:



  • go back to importing vendor source and make sure keyword expansion is disabled and re-merge.

  • be bold and copy all vendor files over the conflict files (thus resolving the conflict). In my case, I knew that no changes we made was a risk-free option.

I went with 2. A rule-based comparison using BeyondCompare confirmed that all files had only "minor" changes.

0


a source


Can you merge again?

execute



Update cvs -kk

before the merge, it will not expand the keywords.
The only keyword that will be a problem is $ Log one

+1


a source


You can program a macro to do this in Emacs without too much trouble - if you're used to emacs / elisp, or if you could probably do it without elisp, using the Keyboard Macro in emacs, then using ^ u ^ u ^ u ^ u ^ u ^ x ^ e (repeat keyboard macro (^ x ^ e) 1024 times, each ^ u increments the count by 4x). The macro will be a simple repetition of the commands required to resolve one conflict in the file. You can also load all files with conflicts into buffers, then use elisp, or perhaps a keyboard macro to resolve conflicts, then switch to the next buffer and repeat.

I wouldn't be surprised if there is an easier way, but it will work. And even if you need to load all files into buffers and then run a keyboard macro, you can do it and do it in a relatively short time.

Pseudo-Emacs:

cvs status | grep conflict >/tmp/foo;
load /tmp/foo into an emacs buffer
edit buffer to remove all but the file/pathnames (use keyboard macros!)
load them all into buffers:
^x^(        (start-macro)
^@^e        (mark (or control-space), then end-of-line)
ESC-w       (copy)
^n^a        (next-line, beginning of line (set up for next iteration))
^x^f        (load-file)
^y          (yank saved)
<RETURN>    (load it - you could resolve conflicts right here and save)
^xb         (switch to buffer)
foo<RETURN> (go back to foo)
^x^)        (end macro)
^x^e        (repeat macro once) or
^u^u^u^u^u^x^e (repeat macro 1024 times or until BEEP)

      

Now you have all the hundreds of files in emacs buffers, and you can set up a macro to grab the next buffer, resolve conflicts and save it, and then repeat that macro N times.

0


a source


Here is a C ++ program I wrote to do this. It compiles in Visual Studio 2008 Express and possibly any other compiler.

This input output is done via redirection, which may not be that convenient, but you can write a cmd file to call it, for example

@echo off
copy /y %1 \temp\t
resolve %2 %3 < \temp\t > %1
del \temp\t

      

The code

// resolve.cpp
#include "stdafx.h"
#include "string.h"

int main(int argc, char* argv[])
{
    const int MAXWIDTH = 10000;
    char line[MAXWIDTH];

    enum { ECHO, OLD, NEW, ERROR };

    int state = ECHO;
    int num = 0;
    int quiet = 0;
    int pick = OLD;

    for (int i = 1; i < argc; ++i)
    {
        if (!strcmp(argv[i],"-h") || !strcmp(argv[i],"--help") || !strcmp(argv[i],"?"))
        {
            printf("Automatically fix CVS merge conflicts.\n"
                "Options:\n"
                " -n use the bottom code, the new code (default uses top, old code).\n"
                " -q quiet\n"
                " -h help\n"
                "use stdin and stdout for input/output and stderr for status.");
            return 0;
        }
        else if (!strcmp(argv[i],"-n"))
        {
            pick = NEW;
        }
        else if (!strcmp(argv[i],"-q"))
        {
            quiet = 1;
        }
        else
            fprintf(stderr,"unknown option %s\n",argv[i]);
    }

    while (fgets(line, MAXWIDTH, stdin))
    {
        // trim trailing whitespace
        for (int i = strlen(line); i >= 0 && line[i] < ' '; --i) 
            line[i] = 0;

        ++num;
        if (!strncmp(line,"<<<<<<< ",8))
        {
            state = (state==ECHO) ? OLD : ERROR;
            if (!quiet)
                fprintf(stderr,"At line: %d\n", num);
        }
        else if (!strcmp(line,"======="))
        {
            state = (state==OLD) ? NEW : ERROR;
        }
        else if (!strncmp(line,">>>>>>> ",8))
        {
            state = (state==NEW) ? ECHO : ERROR;
        }
        else
        {
            if (state == ECHO || state == pick)
                printf("%s\n",line);
            if (!quiet && state != ECHO)
                fprintf(stderr,"%c%s\n", (state==pick) ? '+' : '-', line);
            continue;
        }
        if (!quiet)
            fprintf(stderr,"%s\n",line);
    }
    return 0;
}

      

Disclaimer: You can check your result.

0


a source







All Articles