如何将Mercurial或Git的修订历史导出到CVS?

99

我将与其他人协作处理一个使用CVS的项目代码。我们想要使用分布式版本控制系统来管理我们的工作,当我们结束工作或者定期进行提交时,希望将我们的代码以及所有的修改历史记录提交到CVS。由于我们没有对该项目的CVS仓库进行写操作的权限,因此我们不能够频繁提交。有什么工具可以用来将我们的修改历史记录导出到CVS呢?目前,我们正在考虑使用Git或Mercurial,但如果有其他分布式版本控制系统可以更轻松地完成导出任务,则我们也可以使用该工具。


当你说“分布式CVS”时,我想你的意思是“分布式VCS”,或者“DVCS”,它代表“分布式版本控制系统”。 - Patrick McElhaney
我指的是分布式版本控制系统。 - tatsuhirosatou
3个回答

236

对于那些仍被迫使用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手册中记录,但我认为它们可能会随时发生变化,因此提供如下建议:

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

所有这些选项都可以在命令行上指定,因此您可以安全地跳过此步骤。

增量导入

后续的git cvsimport应该比第一次调用快得多。但是,它会对每个目录(即使只有Attic中的文件)进行cvs rlog操作,因此仍可能需要几分钟时间。如果您已经按照上面建议的设置进行了指定,则只需要执行以下操作:

% git cvsimport

如果您还没有设置配置以指定默认值,则需要在命令行上指定它们:

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

需要注意以下两点:

  1. 确保你处于 Git 存储库的根目录。如果你在其他任何地方,它将尝试进行一次新的cvsimport,这将再次花费很长时间。
  2. 确保你在master分支上,以便更改可以合并(或变基)到本地/主题分支中。

进行本地更改

实践中,我建议始终在分支上进行更改,只有当你准备将这些更改导出回 CVS 存储库时,才合并到master。你可以在自己的分支上使用任何工作流程(合并、变基、压缩等),但是标准的变基规则适用:如果其他任何人都在你的分支上进行更改,则不要进行变基。

导出更改到CVS

git cvsexportcommit 命令允许你将单个提交导出到 CVS 服务器。你可以指定单个提交 ID(或任何描述特定提交的东西,如man git-rev-parse中定义)。然后生成一个 diff,应用于 CVS 检查,并且(可选)使用实际的cvs客户端提交到 CVS。你可以将每个主题分支上的微提交导出,但通常我喜欢在最新的master上创建一个合并提交,并将该合并提交导出到 CVS。当你导出合并提交时,必须告诉 Git 使用哪个提交父项来生成 diff。此外,如果你的合并是快进的(请参阅man git-merge中“HOW MERGE WORKS”部分对快进合并的描述),则这不起作用,因此在执行合并时必须使用--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的man页面上查看这些选项的含义。您也可以在git配置中设置-w选项:

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

如果补丁因任何原因失败,我的经验是你最好手动复制更改的文件,并使用cvs客户端提交。 但是,如果您确保在合并主题分支之前将master与CVS保持最新,则不应该出现此问题。

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

% cvs commit -F .msg file1 file2 file3 etc
下一次执行git cvsimport时(等待至少10分钟),你应该会看到你导出的提交补丁被重新导入到你的本地代码库中。它们将具有不同的提交ID,因为CVS提交将具有不同的时间戳和可能不同的提交者名称(根据是否在初始的cvsimport中设置了作者文件)。如果有多个人需要执行cvsimport,则拥有一个执行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不可行时,它是“下一个最好的选择”。



3
谢谢。这对我非常有帮助,尤其是关于使用非快进式合并将CVS的更改捆绑成单个提交的技巧。 - skiphoppy
8
记录一下,你建议在使用git-cvsimport时使用的-A选项在手册中被提到为“不建议...如果你打算稍后使用git-cvsexportcommit(1)将更改导出回CVS。” 就我个人而言,我喜欢作者原先的表述方式。 - skiphoppy
2
谢谢你的建议。我做过一件很方便的事情,就是在我的 .gitconfig 文件的 [alias] 下面添加了 "cvs = !git cvsimport -k -a"。这样,当我输入 "git cvs" 的时候,它会自动执行正确的操作(从树的顶部开始)。 - bstpierre
1
如果你在Debian上缺少git cvsimport,请尝试执行apt-get install git-cvs - Tino
5
Mac OSX Mavericks完全缺少CVS,而看起来git cvsimport依赖于CVS。在“/ Users / gus / projects / foo / foobar / .git /”中初始化了空的Git存储库。无法执行“cvsps:/Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git-cvsimport line 777中没有这样的文件或目录。无法启动cvsps:没有这样的文件或目录git cvsimport:致命错误:cvsps报告错误。遗憾的是,这不能解决缺少CVS的问题:( - Gus
显示剩余7条评论

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

底线:在导入后检查你的树


3
除了Brian Phillips的回答之外,还有一个名为git-cvsserver的工具,它类似于CVS服务器,但实际上访问的是git仓库...但它有一些限制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接