Один из моих коллег полностью испортил содержимое каталога в нашем основном репозитории 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.
Вы пробовали использовать опцию -d
? (построить подкаталоги)
Насколько я помню, это подразумевается для cvs co
, а не для cvs up
.
Согласно http://www.astro.ku.dk/~aake/MHD/docs/CVS.html, вам нужно следующее:
cvs update -D "30 Dec 2008 23:59"
Мне все еще интересно узнать, есть ли более простой способ. (Несомненно, должен быть более простой способ). В итоге я сделал на ПК с 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
. Я просто не осознавал, что существуют файлы с пробелами.)
У CVS есть несколько проблем, и вы сталкиваетесь с ними с такой проблемой.
CVS ориентирована на файлы, и в ней нет концепции ревизий или снимков. Это означает, что такие изменения, как то, которое вы хотите отменить, немного сложно обработать. Коммиты атомарны внутри данного каталога, а не за его пределами.
Каталоги не версируются. Это означает, что пустые каталоги будут удалены (если вы обновите с помощью -P
) и что вам нужно указать -d
для их создания при оформлении заказа / обновлении.
Итак, отвечая на ваш вопрос, даты, вероятно, единственный способ справиться с этим, потому что вы не использовали теги для создания какой-то версии набора изменений для бедняков.
Мой комментарий по поводу резервных копий заключается в том, что может быть проще восстановить все репо из резервных копий, чем пытаться исправить вещи, в которых CVS не очень хорош.
Я бы посоветовал вам - но это уже другая тема - как можно скорее изменить контроль версий. Поверьте мне, я долгое время имел дело с CVS в рамках Проект FreeBSD и очень быстро понял, насколько ненавистна CVS ... См. здесь, где приведены некоторые из моих взглядов на программное обеспечение для контроля версий.
Если у вас есть резервная копия вашего репозитория (фактические файлы RCS на сервере, например, на ленте), вы можете просто восстановить эту папку на сервере CVS до состояния, в котором она была раньше. Не забудьте остановить сервер CVS перед этим (и перезапустить его после).
Большая проблема, нет полного ответа, просто совет по сценарию, чтобы иметь дело с пробелами в именах файлов.
Вместо
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 для получения нужного момента времени. Много если ...
Я считаю, что ваша вторая команда также должна быть проверкой, а не обновлением. Я не могу оправдать это логикой, поскольку в мире 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
На самом деле ваш первоначальный подход был очень близок к решению. Проблема в том, что присоединение на основе даты некорректно обрабатывает удаленные файлы и каталоги. Сначала вам нужно установить тег для базы кода, к которой вы хотите присоединиться:
mkdir code_base1 && cd code_base1
cvs co -D "2008-12-30" modulename
cvs tag code_base_2008_12_30
Теперь выполните объединение на основе тегов, вычтя все изменения с настоящего момента до 30 декабря 2008 г .:
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. Наконец, зафиксируйте код, как он был 30 декабря 2008 г., как новую ГОЛОВУ:
cvs commit -m "Revert all changes this year"
Обратите внимание, что пометка кода, к которому вы хотите присоединиться, подобным образом не сработает, потому что rtag также некорректно обрабатывает удаленные файлы и каталоги при использовании -D:
cvs rtag -D "2008-12-30" code_base_2008_12_30 modulename
Вы можете посмотреть cvsps. Поищи в Гугле.
Кроме того, с quilt (или patchscripts Эндрю Мортона, с которого quilt началось) и cvsps, можно получить очень близкое приближение к изменениям.
см. http://geocities.com/smcameron/cvs_changesets.html
Если вы или ваш коллега знакомы с git, вы можете использовать git cvsimport
для создания репозитория git, отражающего репозиторий CVS. Отмена фиксации / набора изменений в git тривиальна (с использованием git revert
). Затем вы можете использовать git cvsexportcommit
для отправки фиксации отката в CVS.
Все это может показаться слишком сложным, но по моему опыту git cvsimport
и git cvsexportcommit
работают очень хорошо, если у вас все настроено. В конечном итоге вы получаете всю мощь git лично, даже если проект все еще использует CVS.