如何将修订历史从mercurial或git导出到cvs?
我将与其他人一起使用来自使用CVS的项目的代码。 我们想使用分布式的vcs来完成我们的工作,当我们完成或者偶尔每隔一段时间,我们想把我们的代码和我们所有的修订历史提交给cvs。 我们没有对项目的cvs repo的写权限,所以我们不能经常提交。 我们可以使用什么工具将我们的修订历史导出到CVS? 目前我们正在考虑使用git或者mercurial,但是如果可以使导出更容易,我们可以使用其他分布式vcs。
幸运的是,对于那些仍然被迫使用CVS的人来说,git提供了很好的工具来完成你想做的事情。 我的build议(以及我们在$ work的工作):
创build初始克隆
使用git cvsimport
将CVS修订历史logging复制到git存储库中。 我使用以下调用:
% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \ -A /path/to/authors/file cvs_module_to_checkout
-A
选项是可选的,但它有助于使从CVS导入的修订历史logging看起来更像git(有关如何设置的更多信息,请参阅man git-cvsimport
)。
根据CVS存储库的大小和历史logging,第一次导入将需要很长时间。 如果你想让事情真正发生,那么你可以在上面的命令中添加一个-v。
一旦这个过程完成,你将有一个master
分支,应该反映CVS的HEAD(除了git cvsimport
在默认情况下忽略了最后10分钟的提交以避免捕获一半的提交)。 然后你可以使用git log
和朋友来检查版本库的整个历史logging,就像从一开始就使用git一样。
configuration调整
有一些configuration调整,将使从CVS(以及出口)的增量导入更容易。 这些没有logging在git cvsimport
手册页上,所以我想他们可以改变,恕不另行通知,但FWIW:
% git config cvsimport.module cvs_module_to_checkout % git config cvsimport.r cvs % git config cvsimport.d $CVSROOT
所有这些选项都可以在命令行中指定,这样就可以安全地跳过这一步。
增量import
后续的git cvsimport
应该比第一次调用快得多。 但是,它确实在每个目录(甚至那些在Attic
只有文件的目录)上都有一个cvs rlog
,所以它仍然需要几分钟的时间。 如果你已经指定了上面的build议configuration,你只需要执行:
% git cvsimport
如果你没有设置你的configuration来指定默认值,你需要在命令行中指定它们:
% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout
无论哪种方式,要牢记两件事:
- 确保你在你的git仓库的根目录下。 如果你在其他地方,它会尝试做一个新的
cvsimport
,将永远cvsimport
下去。 - 确保你在你的
master
分支,这样的变化可以合并(或重新)到您的本地/主题分支。
进行本地更改
在实践中,我build议在分支上进行更改,只有当您准备好将这些更改导出到CVS存储库时,才能进行合并。 你可以在你的分支上使用你喜欢的任何工作stream程(合并,重新绑定,压扁等),但是当然也可以使用标准的重新分配规则:如果其他人一直在你的分支上进行修改,不要重新分配。
导出对CVS的更改
git cvsexportcommit
命令允许您将单个提交导出到CVS服务器。 你可以指定一个提交ID(或者任何描述man git-rev-parse
定义的特定提交)。 然后生成差异,应用于CVS签出,然后(可选)使用实际的cvs
客户端提交给CVS。 您可以导出主题分支上的每个微型提交,但通常我喜欢在最新的master
上创build合并提交并将该单一合并提交导出到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的手册页上看到每个选项的含义。 你可以在你的git config中设置-w
选项:
% git config cvsexportcommit.cvsdir /path/to/cvs/checkout
如果补丁由于某种原因失败了,我的经验是,(不幸的是)可能会更好地复制手动更改的文件并使用cvs客户端进行提交。 这不应该发生,但是,如果你确定master
在CVS合并之前合并你的主题分支。
如果提交由于某种原因(networking/权限问题等)而失败,则可以在错误输出结束时将命令打印到terminal,并在CVS工作目录中执行。 它通常看起来像这样:
% cvs commit -F .msg file1 file2 file3 etc
下一次你做一个git cvsimport
(等待至less10分钟),你应该看到你的导出提交补丁重新导入到本地存储库。 他们将有不同的提交ID,因为CVS提交会有不同的时间戳,可能还有一个不同的提交者名称(具体取决于您是否在上面的初始cvsimport
设置了一个作者文件)。
克隆你的CVS克隆
如果您有多个人需要执行cvsimport
,那么使用一个执行cvsimport的git存储库并将所有其他存储库创build为一个克隆会更有效率。 这完美的工作,克隆的存储库可以执行cvsexportcommits就像上面所描述的。 有一个警告,但是。 由于CVS提交的方式通过不同的提交ID返回(如上所述),所以您不希望克隆的分支跟踪中央git存储库。 默认情况下,这是如何git clone
configuration您的存储库,但很容易修复:
% git clone [CENTRAL_REPO_HERE] % cd [NEW_GIT_REPO_DIR_HERE] % git config --unset branch.master.remote % git config --unset branch.master.merge
在你删除了这些configuration之后,当你想从中央资料库中提交新的提交时,你将不得不明确地说出从哪里以及从哪里拉取:
% git pull origin master
总的来说,我发现这个工作stream程非常易于pipe理,而完全迁移到git时的“下一个最好的事情”是不实际的。
您不应该盲目地信任cvsimport,并检查导入的树是否与CVS回购中的内容匹配。 我已经通过使用eclipse CVS的插件共享这个新项目,并发现有不一致的地方。
用同样的提交信息(为了恢复被错误地删除的文件)在不到一分钟的时间内完成的两个提交被分组到一个大提交中,这导致树中缺less文件。
我能够通过修改'fuzz'参数来解决这个问题,不到一分钟。
例:
% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \ -A /path/to/authors/file cvs_module_to_checkout -z 15
底线: 导入后检查你的树
除了Brian Phillips的回答:还有git-cvsserver ,它的function像CVS服务器,但实际上访问git仓库…但它有一些限制。