В репозитории создана новая редакция, однако в рабочем каталоге «test» еще нет информации об этом обновлении. Необходимо выполнить update в этом каталоге, чтобы получить изменения из репозитория. Выполните команду update из каталога «test»:
› cvs update
cvs update: Updating.
U todo.txt
В процессе выполнения команды система изучила содержимое репозитория и рабочего каталога, и обнаружила, что файл todo.txt в репозитории изменился, поэтому он и был обновлён. Буква «U» перед именем файла является сокращением от Update и означает, что файл был обновлен из репозитория целиком, поскольку локальных изменений в нём не было. Что же произойдёт, если перед выполнением команды update изменить файл в рабочем каталоге «test»? Возникнет ситуация, когда требуется совмещение редакций:
• В репозитории редакция 1.2
• В рабочем каталоге «test» изменённая редакция 1.1
В этом случае CVS сначала получает из репозитория изменения к текущей редакции (1.2) относительно исходной локальной редакции (1.1, так как она выглядит в репозитории). Затем CVS совмещает изменения от 1.1 до 1.2 и от 1.1 до текущей локальной копии файла. В результате этих непростых вычислений получается локальный файл, содержащий локальные изменения уже относительно версии 1.2.
RCS file: d:\temp\rep/test/test.c,v
retrieving revision 1.1
retrieving revision 1.2
Merging differences between 1.1 and 1.2 into test.c
M test.c
Буква «М» перед именем файла указывает, что файл был изменен локально, и операция commit еще не проводилась. Иными словами, в рабочем каталоге присутствуют изменения, которых нет в репозитории.
WINCVS Алгоритм, реализующий данную функциональность, довольно сложен, и описание его выходит за рамки этой статьи. Интересующиеся могут поискать информацию по ключевым словам CVS, RCS, diff3, merge.
Обычно CVS в состоянии самостоятельно совместить изменения, однако в случае пересечения изменений или их слишком близкого расположения CVS отказывается совмещать их сам, информирует о конфликте и оставляет рабочий файл в специальном формате. После этого необходимо разрешить конфликт вручную.
WINCVS Обновление рабочего каталога происходит по команде Update selection… из меню Modify. Обновляется каталог или выбранные файлы, в зависимости от того, что выделено.
Разрешение конфликтов
Конфликт может возникнуть при совмещении двух изменений, если они пересекаются или расположены слишком близко друг к другу. Поскольку совмещение (merge) возникает при изменении текста и в репозитории, и в рабочем каталоге, вы не получите конфликта, если не меняете файлов локально (например, просто скачиваете обновления из общедоступного репозитория в Интернете). Вы также не получите конфликта, если никто кроме вас не производит обновления репозитория, например, при использовании CVS лично для себя в домашних условиях. Если же вы работаете в команде, которая активно развивает исходный текст - рано или поздно конфликт неизбежен.
При возникновении конфликта вывод CVS выглядит аналогично нижеследующему.
cvs update: Updating.
RCS file: d:\temp\rep/test/test.c,v
retrieving revision 1.1
retrieving revision 1.2
Merging differences between 1.1 and 1.2 into test.c
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in test.c
C test.c
Буква C помечает файл, в котором был обнаружен конфликт. При указании ключа -q или -Q сообщений о конфликтах будет меньше, но сути это не меняет.
WINCVS CVS разработан так, чтобы никогда не терять изменений. Поэтому во многих случаях он сохраняет резервные копии в файлах с именами начинающимися с «.#» (точка, решётка). В общем случае имя файла выглядит так: «.#исходное-имя-файла.номер.редакции», например «.#test.c.1.1». Например, эти файлы сохранят измененные версии на случай ошибочного разрешения конфликта.
Внутри файла, в котором обнаружен конфликт, проблемные участки текста будут заключены в своеобразные скобки:
‹‹‹‹‹‹‹
зона конфликта
›››››››
Внутри зоны конфликта также будет находиться разделитель «========», который отделяет ваше изменение от проблемного, полученного из репозитория. Полностью маркировка конфликта выглядит так:
‹‹‹‹‹‹‹
имя-файла локальное (Ваше) изменение
=======
редакция из репозитория
››››››› номер редакции в репозитории
Теперь можно разрешить конфликт и оставить код в том состоянии, которое считаете правильным. При необходимости, можно пообщаться с автором конфликтующего изменения и разрешить этот вопрос совместно.
ПРЕДУПРЕЖДЕНИЕ CVS считает, что если время модификации файла (modification time) изменилось с момента обнаружения конфликта, то проблема решена и файл готов к отправке в репозиторий. Поэтому сначала рекомендуется просмотреть все конфликты в файле (их может быть несколько) используя, например, поиск строки “‹‹‹”, понять, как они должны быть решены, и уже потом «одним движением» внести все правки. Если же вы исправите не все конфликты и сохраните файл, а затем выполните операцию commit, в репозитории окажется файл с маркировкой конфликта внутри, и проблемы практически неизбежны. CVS сообщит о таких случаях предупреждением «warning: file `имя-файла' seems to still contain conflict indicators», но версию в репозиторий всё же отправит, поскольку не может быть уверен в своих догадках.
void clear_string(char *p) {
*p=0; // здесь обнаружена ошибка - не было проверки на NULL
}
Ошибку обнаружили двое программистов независимо и, поскольку изменение простейшее, решили тут же её и поправить. Один сделал так:
void clear_string(char *p) {
if (p) *p=0;
}
А другой так:
void clear_string(char *p) {
if (!p) return;
*p=0;
}
Первый поместил версию в репозиторий. Второй попытался тоже обновить репозиторий, на что CVS сообщил, что рабочий каталог устарел и требуется обновление:
cvs commit: Up-to-date check failed for `test.c'
cvs commit: file `todo.txt' had a conflict and has not been modified
Он обновляет свой рабочий каталог командой cvs update и получает сообщение о конфликте. Открыв файл, он обнаруживает следующее:
void clear_string(char *p) {
‹‹‹‹‹‹‹ test.c
if (!p) return;
*p=0;
=======
if (p) *p=0;
››››››› 1.2
}
Разрешение конфликта не займёт много времени, и файл вновь принимает рабочий вид.
void clear_string(char *p) {
if (p) *p=0;
}
После этого можно выполнить операцию commit
Работа с редакциями
Управление редакциями может показаться довольно запутанным процессом, если не разобраться как следует в том, как CVS управляет ими в репозитории. Кратко сформулируем основные правила: