Mercurial转Subversion工作流问题

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仓库时,我遇到了一个问题。

alt text http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/01.png

在我的本地机器上,我有一个已提交并准备好被推送到我们的中间Mercurial仓库的changeset。 在这里,您可以看到它是修订版#2263,哈希值为625...

alt text http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/02.png

我只将此changeset推送到远程仓库。

alt text http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/03.png

到目前为止,一切看起来都很好。 changeset已经被推送了。

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存储库中,我将注意力转回本地客户端。

alt text http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/04.png

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

alt text http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/05.png

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

alt text http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/06.png

无论如何,我将本地存储库更新到新的修订版本。

alt text http://bmurphy.mediafly.com.s3.amazonaws.com/images/mercurial/07.png

现在我已经切换过去了。

alt text 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.

我必须回滚合并以返回工作状态。

我错过了什么?


8
所有的图片都无法显示。 - Paul Wagland
3个回答

22

你没有做错什么,实际上在你的情况下,你看到的行为是预期的结果(对于一个新手来说可能有点令人困惑)。

hgsubversion 真正擅长两件事:

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

你正在尝试将其用作更通用的网关,这是一个非常非常困难的问题。Subversion 对世界有着非常严格的看法,我们必须在其中工作。事实是,在从 Subversion 拉取修订版本之后,只有在使用 hgsubversion 时才能将修订哈希视为最终状态。因此,如果你的开发人员直接在 Mercurial 存储库之间共享 changesets,而没有将 Subversion 作为中间人,则会出现这种情况。

重新定义基线是自动进行且无法选择的,原因非常根本:当你推送时,Subversion 执行该重新定义基线操作。如果你推送时有未拉取的更改,则 Subversion 会为你执行该操作,如果成功(采用一个愚蠢简单的重新基线算法),则接受提交而不指示重新定义基线已发生。我们正在将两种不同的模型拼凑在一起。

我建议一次将所有人都迁移到 Mercurial - 这种混合方法只会使短期内使用 Mercurial 比必要的困难,并可能引起 DVCS 新用户的混淆。


2
@dalroth 需要这样一个过程:用户将 r1:r2 推送到 hg-gateway,hg-gateway 需要自动推送到 Subversion,用户现在必须拉取,最后用户必须执行 hg strip r1 - Harvey
@Harvey - 能否给我澄清一下?我们有一个团队想要切换到hg,但是svn仍然在这里占据主导地位。如果我们建立一个主hg repo,并且只从那里推送/拉取主svn,一切都会没问题吗?更详细的版本:我的老板可以接受我们切换到hg,但前提是先由一个团队进行试点项目。由于有足够多的公共代码(更不用说构建机还在运行svn),完全切换到hg是不可能的。 - moswald
1
@mos:这个方法可行,实际上这也是我个人的做法。关键是要学会修改后的 hg<->hgsubversion<->svn 工作流程。一旦你“掌握”了它的工作原理,就不会有任何问题了。你只需要多输入几个命令。我甚至开始编写脚本来简化这个重复性的过程。典型的流程:[在“hg”存储库中]提交一堆更改;将它们推送到“hgsubversion”;[切换到“hgsubversion”] hg update(hgsubversion 需要这个);hg push 到“svn”(在你推送后自动重新拉取并在本地删除你的变更集);...待续... - Harvey
1
@mos:...[切换回“hg”]从“hgsubversion”中拉取,然后使用“hg strip”删除旧的重复项,因为“hg”不是“hgsubversion”克隆,并且不知道自动删除旧的变更集。 - Harvey

3

首先,让我说一下阅读这样详细的问题描述真是一种愉悦。 :)

当你从远程仓库执行hg push到svn仓库时,出现了问题。以下是你提供的示例输出:

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

我不是hg-subversion的用户,但输出显示在您请求推送过程中,它正在从svn仓库中拉取更改,找到一个新版本,然后在(新拉取版本的)后代之后对您的更改集10c1进行rebaserebase命令将分支历史转换为线性历史,但这样做会更改更改集的父项,从而更改它们的哈希值,这似乎就是发生在您身上的情况。
再次说明,我不是hg-subversion的用户,因此无法确定该pull / rebase是否总是应该发生以及应该如何工作,但是 hgsubversion 维基页面说:
“您可以使用通常的Mercurial命令来处理此存储库。如果您在给定分支上有一系列提交,并且想要将它们移动到该分支的末尾,请在您的工作顶部使用hg rebase --svn命令,然后这些更改集将自动重新基于新的上游工作。”
这使得它听起来通常不是自动的。
我无法完全了解您的介绍,是新的更改集仍然在svn中创建,还是仅在mercurial中创建?
如果它们仅在Mercurial中创建,则一种解决方法是在远程系统上设置svn-gateway repo,并从那里进行推送,永远不要从该repo拉取回mercurial。然后,该repo中的更改集由于rebase具有不同的哈希ID,但它们不会流回到主远程repo和最终用户系统。
更大的修复程序是找出为什么“hg push svn://..正在对所有出站更改集进行重新基础操作”。回答这个问题,行为就会停止。

我尝试仔细查看了这个问题,但仍然没有运气。我找不到一种方法从中间库hg push,而不会自动执行rebase,并且hg rebase --svn没有任何效果,因为它已经是最新版本。 - bmurphy1976
是的,请与hg-subversion团队讨论为什么它正在执行rebase以及是否可以避免。恐怕我只能提供解决方法(3个repo解决方案)。 - Ry4an Brase
@Dalroth,@Ry4an:由于与Subversion的怪癖问题,hgsubversion必须执行rebase。最终解决方案是如果hgsubversion可以检测到您克隆了一个hgsubversion克隆的hg,则它将自动执行必要的下游剥离(strip)和rebase操作。我现在在工作中使用这个过程。它有效,但你需要习惯它。如果您的hgsubversion克隆没有自动与Subversion服务器保持同步(因为必须从SVN拉取,然后将更改rebase到新的tip),则会变得更加复杂。 - Harvey

1

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

我们的目标是干净地为一个使用subversion的项目做出贡献。

  • 为您的所有更改创建一个Subversion分支。将其放入Mercurial中。
    $ cd [svn-checkout] ; svn cp trunk branches/hg-bridge
    $ cd [hgsubversion bridge] ; hg pull ; hg update hg-bridge

  • 检查本地存储库是否有新更改
    $ hg in [repo] # 显示您稍后可以使用的<rev> ID

  • 从本地存储库中拉取要推送到svn的更改
    $ hg pull [repo]

  • 移植您想要贡献的所有更改:
    $ hg graft [rev] [rev] # rev可以是645或b7a92bbb0e0b。最好使用第二个>。
    您需要逐个指定每个rev,
    但您可以在一个命令中移植多个rev。

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接