如何将修订历史记录从 Mercurial 或 git 导出到 cvs?

发布于 2024-07-14 12:39:05 字数 221 浏览 4 评论 0 原文

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

千里故人稀 2024-07-21 12:39:08

幸运的是,对于我们这些仍然被迫使用 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 应该比第一次调用快得多。 但是,它确实会对每个目录(甚至那些在 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)。 然后生成差异,应用于 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 的手册页。 您可以选择在 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 中设置了authors 文件)。

克隆您的 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 时的“下一个最好的事情”是不切实际的。

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):

Creating the Initial Clone

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

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

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

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.

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

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 cvsimport man page so I suppose they could change without notice but, 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 cvsimport should be much faster than the first invocation. It does, however, do an cvs rlog on 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

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 cvsimport that will again take forever.
  2. Make sure you're on your master branch so that the changes can be merged (or rebased) into your local/topic branches.

Making Local Changes

In practice, I recommend always making changes on branches and only merging to master when 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.

Exporting Changes to CVS

The git cvsexportcommit command 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 cvs client. You could export each micro commit on your topic branches but generally I like to create a merge commit on an up-to-date master and 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-merge for a description of a fast-forward merge) so you have to use the --no-ff option when performing the merge. Here's an example:

# 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 -w option in your git config:

% 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 master is up-to-date with CVS before merging your topic branch in.

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 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 cvsimport above).

Cloning your CVS clone

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 clone configures your repository but this is easily remedied:

% 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.

后知后觉 2024-07-21 12:39:08

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

底线:导入后检查您的树

You should not trust cvsimport blindly 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..

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.

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

亽野灬性zι浪 2024-07-21 12:39:08

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文