К счастью для тех из нас, кто все еще вынужден использовать 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
, поэтому я полагаю, что они могут измениться без предварительного уведомления, но, 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
В любом случае, следует помнить две вещи:
- Убедитесь, что вы находитесь в корневом каталоге вашего репозитория git. Если вы где-то еще, он попытается сделать новый
cvsimport
, который снова будет длиться вечно.
- Убедитесь, что вы находитесь в ветке
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 не практична.