首页 文章

如何将修订历史从mercurial或git导出到cvs?

提问于
浏览
100

我将与其他人一起使用来自使用cvs的项目的代码 . 我们希望使用分布式vcs来完成我们的工作,当我们完成或者每隔一段时间我们想要将我们的代码和所有修订历史记录提交给cvs . 我们没有对项目的cvs repo的写访问权限,所以我们不能经常提交 . 我们可以使用什么工具将修订历史导出到cvs?目前我们正在考虑使用git或mercurial但我们可以使用另一个分布式vcs,如果它可以使导出更容易 .

3 回答

  • 21

    幸运的是,对于我们这些仍然被迫使用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 .

    一旦完成此过程,您将拥有一个应该反映CVS的HEAD的 master 分支(除了 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
    

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

    • 确保你在其他任何地方,它会尝试做一个新的 cvsimport ,这将再次永远 .

    • 确保您在 master 分支上,以便可以将更改合并(或重新绑定)到您的本地/主题分支 .

    进行本地更改

    在实践中,我建议总是在分支上进行更改,并且只有在're ready to export those changes back to the CVS repository. You can use whatever workflow you like on your branches (merging, rebasing, squashing, etc) but of course the standard rebasing rules apply: don' t rebase时才会合并到 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
    

    您可以在man page for git-cvsexportcommit上看到每个选项的含义 . 你可以选择在你的git配置中设置 -w 选项:

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

    如果补丁由于某种原因而失败,我的经验是,如果你确定 master 在与你的主题分支合并之前与CVS是最新的,那么你就会发生这种情况 .

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

    % cvs commit -F .msg file1 file2 file3 etc
    

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

    克隆您的CVS克隆

    如果您有多个人需要执行 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

    您不应该盲目信任cvsimport并检查导入的树是否与CVS repo中的匹配 . 我've done this by sharing the new project using 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
    

    底线: check your tree after importing

  • 239

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

相关问题