Как мне отменить большое изменение в CVS? - PullRequest
28 голосов
/ 12 января 2009

Один из моих коллег полностью испортил содержимое каталога в нашем главном хранилище CVS. Мне нужно просто вернуть весь модуль в состояние, в котором он был в конце прошлого года. Что это за команда CVS, пожалуйста?

Он добавил и удалил сотни файлов, поэтому простого «копирования файлов из старой проверки и фиксации» недостаточно.

У меня есть RTFM и STFW, и я попробовал это:

cvs co modulename  # Note no -P option
cvs up -jHEAD -jMAIN:2008-12-30 modulename

Но это не работает - новые файлы, которые он создал, удаляются, но старые файлы и каталоги не воскрешаются. (Я этого не совершал).

Возможно, я могу написать сценарий оболочки для этого, но наверняка эта функциональность уже должна быть в CVS?

Обновление: некоторые уточнения:

  • Я могу получить локальную проверку модуля на определенную дату. Вопрос в том, как вернуть это в CVS.

  • У меня есть резервные копии, но смысл использования системы контроля версий, такой как CVS, заключается в том, что легко получить любое историческое состояние. В следующий раз, когда произойдет что-то подобное, мне может не повезти, если у меня есть резервные копии (например, резервные копии выполняются ежедневно, поэтому я могу потерять работу за день).

  • Я знаю, что CVS старый, и мы должны перейти к чему-то более новому. Но в большой команде с большим количеством инструментов на основе CVS (сценарии проверки и сборки, сервер ночной сборки и т. Д.) Временные затраты на такой переход значительны. (Оценка, обновление скриптов, тестирование, миграция, обучение, потерянное время на разработку, поддержка обеих систем параллельно, так как CVS все еще будет необходим для старых веток). Следовательно, это должно быть запланировано и запланировано руководством.

Обновление № 2: Я собираюсь начать вознаграждение за это. Чтобы претендовать на награду, вы должны объяснить, как вернуть ее, используя обычные команды CVS, а не сценарий хакерской оболочки.

Обновление № 3: Сервер CVS 1.12.13 . Доступ через pserver. Я могу использовать ту же версию CVS на ПК с Linux или клиент CVSNT 2.0.51d в Windows.

Ответы [ 10 ]

27 голосов
/ 25 июня 2009

На самом деле ваш первоначальный подход был очень близок к решению. Проблема в том, что присоединение на основе даты не обрабатывает удаленные файлы и каталоги правильно. Вам необходимо установить тег для той кодовой базы, к которой вы хотите присоединиться первым:

mkdir code_base1 && cd code_base1
cvs co -D "2008-12-30" modulename
cvs tag code_base_2008_12_30

Теперь выполните объединение на основе тегов, вычитая все изменения за период с настоящего времени до 2008-12-30:

cd .. && mkdir code_base2 && cd code_base2
cvs co modulename
cvs update -d -j HEAD -j code_base_2008_12_30  # use -d to resurrect deleted directories

Сравните содержимое code_base1 и code_base2. Они должны быть идентичны, за исключением метаинформации CVS. Наконец, передайте код, как это было в 2008-12-30, в качестве нового заголовка:

cvs commit -m "Revert all changes this year"

Обратите внимание, что пометка кода, к которому вы хотите присоединиться, не будет работать, потому что rtag также неправильно обрабатывает удаленные файлы и каталоги при использовании -D:

cvs rtag -D "2008-12-30" code_base_2008_12_30 modulename
4 голосов
/ 13 января 2009

Есть несколько проблем с CVS, и вы решаете их с такой проблемой.

  1. CVS ориентирован на файл, без понятия набора изменений или снэпшота. Это означает, что с такими изменениями, как те, которые вы хотите отменить, немного сложно справиться. Коммиты являются атомарными в данном каталоге, а не за его пределами.

  2. Каталоги не имеют версий. Это означает, что пустые каталоги будут удалены (если вы обновите с помощью -P), и вы должны указать -d, чтобы создать их при извлечении / обновлении.

Итак, чтобы ответить на ваш вопрос, даты, вероятно, являются единственным способом решения проблемы, поскольку вы не использовали теги для создания версии набора изменений для какого-то бедняка.

Мой комментарий о резервных копиях заключается в том, что может быть проще восстановить весь репозиторий из резервных копий, чем пытаться исправить вещи, в которых CVS не очень хорош.

Я бы посоветовал вам - но это уже другая тема - как можно скорее изменить управление версиями. Поверьте мне, я уже давно занимаюсь CVS в рамках проекта FreeBSD и очень быстро узнаю, насколько ненавистен CVS ... Смотрите здесь , чтобы узнать о некоторых моих взглядах на версию. управляющее программное обеспечение.

2 голосов
/ 14 января 2009

Я считаю, что ваша вторая команда также должна быть проверкой, а не обновлением. Я не могу оправдать это логикой, поскольку в мире CVS нет логики, но она сработала для меня. Попробуйте это:

cvs co -P modulename
cvs co -P -jHEAD -jMAIN:2008-12-30 modulename

Если вы возвращаете ветку, отличную от HEAD, например X, передайте аргумент -rX в обеих командах:

cvs co -P -rX modulename
cvs co -P -rX -jHEAD -jMAIN:2008-12-30 modulename
1 голос
/ 28 июня 2009

Вы можете посмотреть в cvsps. Google это.

Кроме того, с помощью quilt (или сценариев-патчей Эндрю Мортона, с которых начиналось quilt) и cvsps можно получить очень близкое приближение наборов изменений.

см. http://geocities.com/smcameron/cvs_changesets.html

1 голос
/ 12 января 2009

Мне все еще интересно узнать, есть ли более простой способ. (Там, безусловно, должен быть более легкий путь). В конечном итоге я сделал на ПК с Linux bash:

# Get woking copy we're going to change
cd ~/work
rm -rf modulename
cvs up -dP modulename
cd modulename

# Remove all files
find . -name CVS -prune -o -type f -print | xargs cvs rm -f

# Get the old revision
cd ~
mkdir scratch
cd scratch
cvs -q co -D 2008-12-31 modulename
cd modulename

# Copy everything to the working dir and do "cvs add" on it
find . -name CVS -prune -o -type f -print | \
    xargs tar c | \
    (cd ~/work/modulename && tar xv | \
    xargs cvs add)

# Check everything is OK before we commit
cd ~/work/modulename
cvs -nq up

# it gave me an error on readme.txt because I'd deleted and then added it, so:
mv readme.txt x # save good rev
cvs add readme.txt # resurrect the bad rev
mv x readme.txt # clobber file with good rev

# Commit it
cvs commit -m "Revert all changes this year"

# Delete now-empty directories
cvs -q up -dP

# Double-check everything is back how it was
diff -ur -xCVS ~/scratch/modulename ~/work/modulename

Затем я обнаружил, что все еще существуют различия - мой коллега добавил имена файлов, содержащие пробелы, которые не были удалены вышеуказанным процессом. Я должен был удалить их отдельно. (Я должен был использовать find ... -print0 вместо -print и передать аргумент -0 в xargs. Я просто не осознавал, что были файлы с пробелами.)

0 голосов
/ 19 августа 2011

Если вы или ваш коллега знакомы с git, вы можете использовать git cvsimport, чтобы создать репозиторий git, отражающий репозиторий CVS. Отменить коммит / changeset в git тривиально (используя git revert). Затем вы можете использовать git cvsexportcommit для отправки возврата в CVS.

Это может показаться слишком сложным, но по моему опыту git cvsimport и git cvsexportcommit работают очень хорошо, как только вы все настроите. Вы получаете всю мощь git лично, хотя в проекте все еще используется CVS.

0 голосов
/ 14 января 2009

Большая проблема, нет полного ответа, просто подсказка по написанию сценариев для работы с пробелами в именах файлов.

Вместо

find ... | xargs tar c - | ...

попробуйте поставить

find ... | perl -e '@names = <>;' -e 'chomp @names;' -e 'system( "tar", "c", "-", @names);' | ...

таким образом, создание вашего архива (или аналогичные операции) не будет страдать от пробелов в именах, синтаксический анализ оболочки argv пропускается до вызова tar.

Еще одна вещь, на случай, если она действительно работает: если есть утилита CVS to SVN, используйте ее (я предполагаю, что такая утилита будет извлекать удаленные файлы с "чердака CVS"), и , если он сохраняет каждый момент времени как контрольную точку уровня проекта (поскольку SVN делает это, в отличие от CVS), используйте SVN для получения нужного момента времени. Лот если ...

0 голосов
/ 13 января 2009

Если у вас есть резервная копия вашего хранилища (фактические файлы RCS на сервере, например, на ленте), вы можете просто восстановить эту папку на сервере CVS до состояния, в котором она была раньше. Не забудьте остановить сервер CVS перед этим (и перезапустить его потом).

0 голосов
/ 12 января 2009

Согласно http://www.astro.ku.dk/~aake/MHD/docs/CVS.html, вам нужно следующее:

cvs update -D "30 Dec 2008 23:59"
0 голосов
/ 12 января 2009

Вы пытались использовать опцию -d? (построить подкаталоги)

Насколько я помню, это подразумевается для cvs co, но не для cvs up.

...