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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/584522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:11:47  来源:igfitidea点击:

How to export revision history from mercurial or git to cvs?

gitmercurialexportcvsgit-cvs

提问by tatsuhirosatou

I'm going to be working with other people on code from a project that uses cvs. We want to use a distributed vcs to make our work and when we finish or maybe every once in a while we want to commit our code and all of our revision history to cvs. We don't have write access to the project's cvs repo so we can't commit very frequently. What tool can we use to export our revision history to cvs? Currently we were thinking of using git or mercurial but we could use another distributed vcs if it could make the export easier.

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

回答by Brian Phillips

Fortunately for those of us who are still forced to use CVS, git provides pretty good tools to do exactly what you're wanting to do. My suggestions (and what we do here at $work):

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

Creating the Initial Clone

创建初始克隆

Use git cvsimportto clone the CVS revision history into a git repository. I use the following invocation:

用于git cvsimport将 CVS 修订历史克隆到 git 存储库中。我使用以下调用:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout

The -Aoption is optional but it helps to make your revision history that's imported from CVS look more git-like (see man git-cvsimportfor more info on how this is set up).

-A选项是可选的,但它有助于使从 CVS 导入的修订历史看起来更像 git(man git-cvsimport有关如何设置的更多信息,请参见)。

Depending on the size and history of the CVS repository, this first import will take a VERY long time. You can add a -v to the above command if you want the peace of mind that something is in fact happening.

根据 CVS 存储库的大小和历史,第一次导入需要很长时间。如果您想让事情确实发生了,您可以在上面的命令中添加 -v。

Once this process is completed, you will have a masterbranch that should reflect CVS's HEAD (with the exception that git cvsimportby default ignores the last 10 minutes worth of commits to avoid catching a commit that is half-finished). You can then use git logand friends to examine the entire history of the repository just as if it had been using git from the beginning.

一旦这个过程完成,你将有一个master应该反映 CVS 的 HEAD的分支(除了git cvsimport默认情况下忽略最后 10 分钟的提交以避免捕获半完成的提交)。然后git log,您可以使用和朋友来检查存储库的整个历史记录,就像它从一开始就使用 git 一样。

Configuration Tweaks

配置调整

There are a few configuration tweaks that will make incremental imports from CVS (as well as exports) easier in the future. These are not documented on the git cvsimportman page so I suppose they could change without notice but, FWIW:

有一些配置调整将使将来从 CVS(以及导出)的增量导入变得更容易。这些没有记录在git cvsimport手册页上,所以我想他们可以在没有通知的情况下改变,但是,FWIW:

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

All of these options can be specified on the command line so you could safely skip this step.

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

Incremental Imports

增量导入

Subsequent git cvsimportshould be much faster than the first invocation. It does, however, do an cvs rlogon every directory (even those that have only files in Attic) so it can still take a few minutes. If you've specified the suggested configs above, all you need to do is execute:

后续git cvsimport应该比第一次调用快得多。但是,它确实cvs rlog对每个目录(即使是那些只有Attic. 如果你已经指定了上面建议的配置,你需要做的就是执行:

% git cvsimport

If you haven't set up your configs to specify the defaults, you'll need to specify them on the command line:

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

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

Either way, two things to keep in mind:

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

  1. Make sure you're in the root directory of your git repository. If you're anyplace else, it will try to do a fresh cvsimportthat will again take forever.
  2. Make sure you're on your masterbranch so that the changes can be merged (or rebased) into your local/topic branches.
  1. 确保您位于 git 存储库的根目录中。如果你在其他任何地方,它会尝试做一个新鲜的cvsimport,将再次需要永远。
  2. 确保您在您的master分支上,以便可以将更改合并(或重新定位)到您的本地/主题分支中。

Making Local Changes

进行本地更改

In practice, I recommend always making changes on branches and only merging to masterwhen you'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 if anyone else has been basing their changes on your branch.

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

Exporting Changes to CVS

将更改导出到 CVS

The git cvsexportcommitcommand allows you to export a single commit out to the CVS server. You can specify a single commit ID (or anything that describes a specific commit as defined in man git-rev-parse). A diff is then generated, applied to a CVS checkout and then (optionally) committed to CVS using the actual cvsclient. You could export each micro commit on your topic branches but generally I like to create a merge commit on an up-to-date masterand export that single merge commit to CVS. When you export a merge commit, you have to tell git which commit parent to use to generate the diff. Also, this won't work if your merge was a fast-forward (see the "HOW MERGE WORKS" section of man git-mergefor a description of a fast-forward merge) so you have to use the --no-ffoption when performing the merge. Here's an example:

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

You can see what each of those options mean on the man page for git-cvsexportcommit. You do have the option of setting the -woption in your git config:

您可以在git-cvsexportcommit手册页上查看每个选项的含义。您可以-w选择在 git 配置中设置选项:

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

If the patch fails for whatever reason, my experience is that you'll (unfortunately) probably be better off copying the changed files over manually and committing using the cvs client. This shouldn't happen, however, if you make sure masteris up-to-date with CVS before merging your topic branch in.

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

If the commit fails for whatever reason (network/permissions issues, etc), you can take the command printed to your terminal at the end of the error output and execute it in your CVS working directory. It usually looks something like this:

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

% cvs commit -F .msg file1 file2 file3 etc

The next time you do a git cvsimport(waiting at least 10 minutes) you should see the patch of your exported commit re-imported into your local repository. They will have different commit IDs since the CVS commit will have a different timestamp and possibly a different committer name (depending on whether you set up an authors file in your initial cvsimportabove).

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

Cloning your CVS clone

克隆您的 CVS 克隆

If you have more than one person needing to do the cvsimport, it would be more efficient to have a single git repository that performs the cvsimport and have all the other repositories created as a clone. This works perfectly and the cloned repository can perform cvsexportcommits just as described above. There is one caveat, however. Due to the way CVS commits come back through with different commit IDs (as described above), you don't want your cloned branch to track the central git repository. By default, this is how git cloneconfigures your repository but this is easily remedied:

如果您有不止一个人需要执行该操作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

After you've removed these configs, you will have to explicitly say where and what to pull from when you want to pull in new commits from the central repository:

删除这些配置后,当您想从中央存储库中提取新提交时,您必须明确说明从何处提取以及从何处提取:

% git pull origin master


Overall, I've found this work-flow to be quite manageable and the "next best thing" when migrating completely to git isn't practical.

总的来说,我发现这个工作流程非常易于管理,并且在完全迁移到 git 时“下一个最好的事情”是不切实际的。

回答by shil88

You should not trust cvsimportblindly and check if the imported tree matches what is in the CVS repo. I've done this by sharing the new project using eclipse CVS' plug-in and found that there were inconsistencies..

您不应该盲目地相信cvsimport并检查导入的树是否与 CVS 存储库中的内容匹配。我已经通过使用eclipse CVS的插件共享新项目来做到这一点的,发现存在不一致..

Two commits that were done in less than a minute with the same commit message (in order to revert a wrongfully deleted file) were grouped into one big commit, which resulted in a missing file from the tree..

在不到一分钟的时间内完成的具有相同提交消息的两次提交(为了恢复错误删除的文件)被分组到一个大提交中,这导致树中丢失了一个文件。

I was able to solve this problem by modifying the 'fuzz' parameter to less than a minute.

我能够通过将 'fuzz' 参数修改为不到一分钟来解决这个问题。

example:

例子:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout -z 15

bottom line: check your tree after importing

底线:导入后检查您的树

回答by Jakub Nar?bski

In addition to Brian Phillips answer: there is also git-cvsserverwhich functions like CVS server but actually access git repository... but it has some limitations.

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