100

我将与其他人一起处理使用 cvs 的项目中的代码。我们想使用分布式 vcs 来完成我们的工作,当我们完成时,或者可能每隔一段时间,我们想将我们的代码和我们所有的修订历史提交到 cvs。我们没有对项目的 cvs repo 的写入权限,因此我们不能非常频繁地提交。我们可以使用什么工具将我们的修订历史导出到 cvs?目前我们正在考虑使用 git 或 mercurial,但如果它可以使导出更容易,我们可以使用另一个分布式 vcs。

4

3 回答 3

237

幸运的是,对于我们这些仍然被迫使用 CVS 的人来说,git 提供了非常好的工具来做你想做的事情。我的建议(以及我们在 $work 所做的事情):

创建初始克隆

用于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 的 HEAD 的分支(除了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对每个目录(甚至那些只有文件 in 的目录Attic)执行一次操作,因此仍然需要几分钟时间。如果您已经指定了上面建议的配置,您需要做的就是执行:

% git cvsimport

如果您尚未设置配置以指定默认值,则需要在命令行中指定它们:

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

无论哪种方式,要记住两点:

  1. 确保您位于 git 存储库的根目录中。如果你在其他地方,它会尝试做一个新的cvsimport,这将再次需要永远。
  2. 确保您在您的master分支上,以便可以将更改合并(或重新定位)到您的本地/主题分支中。

进行本地更改

master在实践中,我建议始终在分支上进行更改,并且仅在您准备好将这些更改导出回 CVS 存储库时才合并。您可以在您的分支上使用您喜欢的任何工作流程(合并、变基、压缩等),但当然标准变基规则适用:如果其他人已经将他们的更改基于您的分支,则不要变基。

将更改导出到 CVS

git cvsexportcommit命令允许您将单个提交导出到 CVS 服务器。您可以指定单个提交 ID(或任何描述特定提交的内容,如 中定义man git-rev-parse)。然后生成一个差异,应用于 CVS 签出,然后(可选)使用实际cvs客户端提交给 CVS。您可以在主题分支上导出每个微提交,但通常我喜欢在最新的上创建合并提交master并将该单个合并提交导出到 CVS。导出合并提交时,您必须告诉 git 使用哪个提交父级来生成差异。此外,如果您的合并是快进的,这将不起作用(有关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 config 中设置选项:

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

如果补丁由于某种原因失败,我的经验是(不幸的是)您最好手动复制更改的文件并使用 cvs 客户端提交。但是,如果您在合并主题分支之前确保masterCVS 是最新的,则不应该发生这种情况。

如果提交由于任何原因(网络/权限问题等)失败,您可以在错误输出的末尾将命令打印到终端并在 CVS 工作目录中执行它。它通常看起来像这样:

% cvs commit -F .msg file1 file2 file3 etc

下次您执行git cvsimport(至少等待 10 分钟)时,您应该会看到导出的提交的补丁重新导入到本地存储库中。它们将具有不同的提交 ID,因为 CVS 提交将具有不同的时间戳,并且可能具有不同的提交者名称(取决于您是否在cvsimport上面的初始设置中设置了作者文件)。

克隆你的 CVS 克隆

如果您有不止一个人需要cvsimport执行 .git,那么拥有一个执行 cvsimport 的 git 存储库并将所有其他存储库创建为克隆会更有效。这完美地工作,并且克隆的存储库可以执行 cvsexportcommits,就像上面描述的那样。但是,有一个警告。由于 CVS 提交通过不同的提交 ID 返回的方式(如上所述),您不希望克隆的分支跟踪中央 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 时“下一个最好的事情”是不切实际的。

于 2009-02-25T14:42:02.517 回答
22

您不应该盲目相信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

底线:导入后检查你的树

于 2010-06-28T15:12:42.337 回答
3

除了 Brian Phillips 的回答:还有git-cvsserver,它的功能类似于 CVS 服务器,但实际上可以访问 git 存储库……但它有一些限制。

于 2009-02-25T20:43:34.113 回答