23

我们正在从 Subversion 迁移到 Mercurial。为了便于迁移,我们正在创建一个中间 Mercurial 存储库,它是我们的 Subversion 存储库的克隆。所有开发人员都将开始切换到 Mercurial 存储库,我们将定期将更改从中间 Mercurial 存储库推送到现有的 Subversion 存储库。一段时间后,我们将简单地废弃 Subversion 存储库,中间的 Mercurial 存储库将成为新的记录系统。

Dev 1 Local --+--> Mercurial --+--> Subversion
Dev 2 Local --+                +
Dev 3 Local --+                +
Dev 4 -------------------------+

我一直在对此进行测试,但是当我将更改从本地存储库推送到中间 Mercurial 存储库,然后再推送到我们的 Subversion 存储库时,我一直遇到问题。

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/01.png

在我的本地机器上,我有一个已提交并准备好推送到我们的中间 Mercurial 存储库的变更集。在这里你可以看到它是带有哈希 625 的修订 #2263...

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/02.png

我只将此变更集推送到远程存储库。

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/03.png

到目前为止,一切看起来都很好。变更集已被推送。

hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

我现在切换到远程存储库,并更新工作目录。

hg push
pushing to svn://...
searching for changes
[r3834] bmurphy: database namespace
pulled 1 revisions
saving bundle to /srv/hg/repository/.hg/strip-backup/62539f8df3b2-temp
adding branch
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
rebase completed

接下来,我将更改推送到 Subversion,效果很好。此时,更改位于 Subversion 存储库中,我将注意力返回到本地客户端。

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/04.png

我将更改拉到本地计算机。嗯?我现在有两个变更集。我的原始变更集现在显示为本地分支。

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/05.png

另一个变更集有一个新的修订号 2264 和一个新的哈希 10c1...

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/06.png

无论如何,我将本地存储库更新为新版本。

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/07.png

我现在换了。

替代文字 http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/08.png

因此,我最后单击“确定并标记传出变更集”,如您所见,Mercurial 仍然希望推出我以前的变更集,即使它们已经被推送。

显然,我做错了什么。

我也无法合并这两个修订版。如果我在本地机器上合并这两个修订,我最终会得到一个“合并”提交。当我将该合并提交推送到中间 Mercurial 存储库时,我无法再将更改推送到我们的 Subversion 存储库。我最终遇到以下问题:

hg update
0 files updated, 0 files merged, 0 files removed, 0 files unresolved

hg push
pushing to svn://...
searching for changes
abort: Sorry, can't find svn parent of a merge revision.

我必须回滚合并才能恢复到工作状态。

我错过了什么?

4

3 回答 3

22

您没有做错任何事情,实际上在您的情况下,您看到的行为是预期的(如果对新的 Mercurial 用户有些困惑)结果。

hgsubversion 对两件事非常有用:

  1. 使用 Mercurial 作为 Subversion 的客户端,无需在 svn 之外交换更改
  2. 将 Subversion 存储库转换为 Mercurial

您正在尝试将其用作更通用的网关,这是一个困难得多的问题。Subversion 对世界有非常严格的看法,我们必须在这个范围内工作。事情的真相是,只有在从 Subversion 中提取修订后使用 hgsubversion 时,才能将修订哈希视为最终版本。因此,如果您的开发人员在没有 Subversion 作为中介的情况下直接在 Mercurial 存储库之间共享变更集,就会发生这种情况。

rebase 是自动的和非可选的,因为一个非常基本的原因:Subversion 在你推送时执行那个 rebase。如果你在推送时有未拉取的更改,Subversion 会为你做那个变基,如果成功(使用一个愚蠢简单的变基算法)它会接受提交,而没有任何变基发生的迹象。我们正在拼凑两个不同的模型。

我建议立即将所有人转移到 Mercurial - 像这样的混合方法只会在短期内使使用 Mercurial 变得比实际需要的更加困难,并且可能会使刚接触 DVCS 的用户感到困惑。

于 2010-03-25T15:15:57.860 回答
3

First, let me say what a pleasure it was to read such a detailed question write up. :)

The problem is happening when you do the hg push to the svn repo from remote. Here's that output from your example:

hg push
pushing to svn://...
searching for changes
[r3834] bmurphy: database namespace
pulled 1 revisions
saving bundle to /srv/hg/repository/.hg/strip-backup/62539f8df3b2-temp
adding branch
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
rebase completed

I'm not a hg-subversion user, but that output says that in the process of doing the push you requested, it's pulling the changes from the svn repo, finding a new revision and then doing a rebase of your changeset 10c1 after (descendent of) the newly pulled revision. The rebase command takes branching histories and turns the into linear histories, but in doing so it changes the parents of the changesets, which changes their hashes, which looks like just what's happening to you.

Again, not a hg-subversion user, so I can't say if that pull/rebase is always supposed to happen and how that's supposed to work, but the hgsubversion wiki page says:

You can use the usual Mercurial commands to work with this repository. If you have a series of commits on a given branch, and want to move them to the tip of that branch, use the hg rebase --svn command while on the tip of your work, and those changesets will automatically be rebased over top of the new upstream work.

which makes it sound not normally automatic.

I couldn't quite tell from your intro, are new changesets still being created in svn, or are they created only in mercurial?

If they're only created in mercurial then one work-around would be to set up a svn-gateway repo on the remote system, and do the push from there, and never pull from that repo back into mercurial. Then the changesets in that repo would have different hashids due to the rebase, but they'd not flow back into the main remote repo and the end user systems.

The bigger fix though is to figure out why "hg push svn://.. is rebasing all the outbound changesets". Answer that one and the behavior will stop.

于 2010-03-24T04:23:52.490 回答
1

我们现在使用graft 命令来做类似的事情。实际上,我们在推送之前重新创建每个变更集,以避免推送合并变更集。

我们的目标是干净地为使用颠覆的项目做出贡献。

  • 为所有更改创建一个颠覆分支。在 Mercurial 中获取它。
    $ cd [svn-checkout] ; svn cp trunk branches/hg-bridge
    $cd [hgsubversion bridge] ; hg pull ; hg update hg-bridge

  • 检查您的本地存储库是否有新更改
    $hg in [repo] # shows <rev> IDs you can use later

  • 从本地 repo 中提取您想要进入 svn 的更改
    $hg pull [repo]

  • 嫁接您想要贡献的所有更改:
    $hg graft [rev] [rev] # rev could be 645 or b7a92bbb0e0b. Best use the second>.
    您需要单独指定每个 rev,
    但您可以在一个命令中嫁接多个 rev。

  • 检查您要推送的内容:
    $hg outgoing

  • 推送更改:
    $hg push
    可能会显示一些不相关的拉取修订
    ,并且应该将您的新修订显示为拉取,
    以及备份包的路径(您不需要)。(注释也可以在 GPLv2 或更高版本下使用)

于 2012-05-25T08:48:48.127 回答