Как экспортировать историю изменений из Mercurial или Git в CVS?

Я собираюсь работать с другими людьми над кодом из проекта, который использует cvs. Мы хотим использовать распределенный vcs для своей работы, и когда мы закончим или, возможно, время от времени, мы хотим зафиксировать наш код и всю нашу историю изменений в cvs. У нас нет прав на запись в репозиторий cvs проекта, поэтому мы не можем совершать очень часто. Какой инструмент мы можем использовать для экспорта нашей истории изменений в cvs? В настоящее время мы думали об использовании git или mercurial, но мы могли бы использовать другой распределенный vcs, если это могло бы облегчить экспорт.

3 ответа

Решение

К счастью для тех из нас, кто все еще вынужден использовать CVS, git предоставляет довольно хорошие инструменты для того, чтобы делать именно то, что вы хотите. Мои предложения (и что мы делаем здесь, на $ работа):

Создание начального клона

использование git cvsimport клонировать историю изменений CVS в репозиторий git. Я использую следующий вызов:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout

-A опция не обязательна, но она помогает сделать вашу историю ревизий, импортированную из CVS, более похожей на git (см. man git-cvsimport для получения дополнительной информации о том, как это настроено).

В зависимости от размера и истории репозитория CVS этот первый импорт займет ОЧЕНЬ много времени. Вы можете добавить -v к вышеприведенной команде, если хотите, чтобы что-то происходило на самом деле.

После завершения этого процесса у вас будет master ветвь, которая должна отражать заголовок CVS (за исключением того, что git cvsimport по умолчанию игнорирует последние 10 минут коммитов, чтобы избежать перехвата коммита, который наполовину завершен). Вы можете использовать git log и друзья, чтобы изучить всю историю хранилища так же, как если бы он использовал git с самого начала.

Настройки твиков

Существует несколько настроек, которые в будущем упростят добавочный импорт из CVS (а также экспорт). Они не документированы на git cvsimport man-страницу, так что я полагаю, что они могут измениться без уведомления, но, FWIW:

% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT

Все эти параметры можно указать в командной строке, чтобы вы могли спокойно пропустить этот шаг.

Добавочный импорт

последующее git cvsimport должно быть намного быстрее, чем первый вызов. Это, однако, сделать cvs rlog на каждый каталог (даже те, которые имеют только файлы в Attic) так что это может занять несколько минут. Если вы указали предложенные конфиги выше, все, что вам нужно сделать, это выполнить:

% git cvsimport

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

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

В любом случае, нужно помнить две вещи:

  1. Убедитесь, что вы находитесь в корневом каталоге вашего репозитория git. Если вы где-то еще, он постарается сделать свежий cvsimport это снова займет вечность.
  2. Убедитесь, что вы на master ветвь, чтобы изменения могли быть объединены (или перебазированы) в ваши локальные / тематические ветки.

Внесение локальных изменений

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

Экспорт изменений в CVS

git cvsexportcommit Команда позволяет вам экспортировать один коммит на сервер CVS. Вы можете указать один идентификатор фиксации (или все, что описывает конкретную фиксацию, как определено в man git-rev-parse). Затем генерируется diff, применяется к проверке CVS, а затем (необязательно) фиксируется в CVS с использованием фактического cvs клиент. Вы можете экспортировать каждый микро-коммит в ветвях вашей темы, но обычно мне нравится создавать коммит-слияние в актуальном состоянии. master и экспортировать этот единственный коммит слияния в CVS. Когда вы экспортируете коммит слияния, вы должны указать git, какой родительский коммит использовать для генерации diff. Кроме того, это не сработает, если ваше слияние было ускоренным (см. Раздел "КАК MERGE РАБОТАЕТ" man git-merge для описания быстрого слияния), поэтому вы должны использовать --no-ff опция при выполнении слияния. Вот пример:

# on master
% git merge --no-ff --log -m "Optional commit message here" topic/branch/name
% git cvsexportcommit -w /path/to/cvs/checkout -u -p -c ORIG_HEAD HEAD

Вы можете увидеть, что означает каждый из этих параметров на странице руководства для git-cvsexportcommit. У вас есть возможность установить -w опция в вашем конфиге git:

% git config cvsexportcommit.cvsdir /path/to/cvs/checkout

Если по какой-либо причине патч не сработает, то, по моему опыту, вам (к сожалению), вероятно, будет лучше скопировать измененные файлы вручную и выполнить фиксацию с помощью клиента cvs. Это не должно произойти, однако, если вы убедитесь, master обновлен до CVS, прежде чем объединить ветку вашей темы в.

Если фиксация не удалась по какой-либо причине (проблемы с сетью / разрешениями и т. Д.), Вы можете взять команду, напечатанную на вашем терминале в конце вывода ошибки, и выполнить ее в рабочем каталоге CVS. Обычно это выглядит примерно так:

% cvs commit -F .msg file1 file2 file3 etc

В следующий раз вы сделаете git cvsimport (ожидание не менее 10 минут) вы должны увидеть, как патч вашей экспортированной фиксации повторно импортируется в ваш локальный репозиторий. Они будут иметь разные идентификаторы коммитов, поскольку фиксация CVS будет иметь разную временную метку и, возможно, другое имя коммиттера (в зависимости от того, настроили ли вы файл авторов в исходном файле). cvsimport выше).

Клонирование вашего клона CVS

Если у вас есть несколько человек, нуждающихся в cvsimport было бы более эффективно иметь один репозиторий git, который выполняет cvsimport, а все остальные репозитории создавались как клон. Это работает отлично, и клонированный репозиторий может выполнять коммиты cvsexport, как описано выше. Однако есть одна оговорка. Из-за способа, которым коммиты CVS возвращаются с разными идентификаторами коммитов (как описано выше), вы не хотите, чтобы ваша клонированная ветвь отслеживала центральное хранилище git. По умолчанию это как git clone настраивает ваш репозиторий, но это легко исправить:

% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge

После того, как вы удалили эти конфиги, вам нужно будет явно указать, куда и что извлекать, когда вы хотите получить новые коммиты из центрального репозитория:

% git pull origin master

В целом, я нашел этот рабочий процесс вполне управляемым, и "следующая лучшая вещь" при полной миграции на git не практична.

Вы не должны слепо доверять cvsimport и проверять, соответствует ли импортированное дерево тому, что находится в репозитории CVS. Я сделал это, поделившись новым проектом с помощью плагина eclipse CVS и обнаружил, что были несоответствия.

Два коммита, которые были выполнены менее чем за минуту с одним и тем же сообщением коммита (для возврата ошибочно удаленного файла), были сгруппированы в один большой коммит, что привело к отсутствию файла в дереве.

Я смог решить эту проблему, изменив параметр 'fuzz' до менее минуты.

пример:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout -z 15

Итог: проверьте ваше дерево после импорта

В дополнение к ответу Брайана Филлипса: есть также git-cvsserver, который работает как сервер CVS, но на самом деле имеет доступ к репозиторию git... но у него есть некоторые ограничения.

Другие вопросы по тегам