Разрешение массового конфликта
-
23-08-2019 - |
Вопрос
Я использую CVS, и после слияния у меня возникают сотни конфликтов.Ни один из конфликтов не является проблемой (это незначительные изменения в результате различий в расширении ключевых слов в магистрали и ветви).
Я знаю, что в файлы не было внесено никаких изменений, поскольку это просто слияние ветки поставщика с магистралью.Несколько десятков файлов были случайным образом проверены, чтобы подтвердить это.
Есть ли быстрый способ разрешить все конфликты, не выполняя каждый из них вручную?(В моем распоряжении есть TortoiseCVS, WinCvs и командная строка).
Решение 3
Я собираюсь ответить на свой собственный вопрос, поскольку решение EMACS, предложенное @jesup, было непрактичным для тех, кто не пользовался EMACS 15 лет!
В моем случае, потому что я знал, что единственный конфликт был в расширении ключевых слов $LOG $, и я действительно не заботился о содержании комментариев.Я видел два возможных решения:
вернитесь к импорту источника поставщика и убедитесь, что расширение ключевого слова отключено, и повторите слияние.
наберитесь смелости и скопируйте все файлы поставщика поверх файлов конфликта (разрешив таким образом конфликт).В моем случае я знал, что с нашей стороны не было внесено никаких изменений, это был вариант без риска.
Я пошел с 2.Сравнение на основе правил с использованием За пределами сравнения подтвердил, что во всех файлах были только "несущественные" изменения.
Другие советы
можете ли вы снова выполнить слияние?
сделайте
обновление резюме -kk
до слияния это не приведет к расширению ключевых слов.
Единственное ключевое слово, которое будет проблемой, - это $Log
Вы могли бы запрограммировать макрос для выполнения этого в Emacs без особых проблем - если вы привыкли к emacs / elisp, или если вы, вероятно, могли бы сделать это без elisp, используя макрос клавиатуры в emacs, затем используя ^u ^ u ^ u ^ u ^ u ^ x ^ e (повторите макрос клавиатуры (^x ^ e) 1024 раза;каждый ^u увеличивает количество в 4 раза).Макрос будет представлять собой простое повторение команд, необходимых для разрешения одного конфликта в файле.Вы также могли бы загрузить все файлы с конфликтами в буферы, затем использовать elisp или, возможно, клавиатурный макрос для разрешения конфликтов, затем переключиться на следующий буфер и повторить это.
Я не удивлюсь, если есть более простой способ, но это сработало бы.И даже если вам придется загрузить все файлы в буферы, а затем запустить макрос клавиатуры, вы можете сделать это за относительно короткое время.
Псевдо-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)
Теперь у вас есть все сотни файлов в буферах emacs, и вы можете настроить макрос для захвата следующего буфера, разрешения конфликтов и сохранения его, а затем повторить это макрос N раз.
Вот программа на C ++, которую я написал для этого.Он компилируется в Visual Studio 2008 Express и, вероятно, в любом другом компиляторе.
Этот ввод осуществляется с помощью перенаправления, что, возможно, не так удобно, но вы можете написать cmd-файл для его вызова, например
@echo off
copy /y %1 \temp\t
resolve %2 %3 < \temp\t > %1
del \temp\t
Код является
// 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;
}
Отказ от ответственности:Возможно, вы захотите проверить свои выходные данные.