Mercurial 中的 Reparenting:如何将两个独立的 svn 克隆重新组合在一起?

发布于 11-05 22:09 字数 938 浏览 4 评论 0原文

情况是这样的:开发人员 Foo 从我们的 svn 存储库创建了一个 hg 存储库。 Foo 的 hg repo 只是 svn 中主干的浅层克隆(没有 svn 分支、标签等,并且历史记录不完整[大约 100 个变更集])。开发人员 Bar 做了同样的事情,但克隆了整个 svn 存储库,包括整个历史记录、分支、标签等。Foo 和 Bar 都在其存储库上进行了分支开发。

两个存储库都有一个共同的 SVN 祖先,但每个 hg 存储库都有不同的版本号。我想将 Foo 的更改从共同祖先重新分配到 Bar 的存储库上。这是我正在寻找的内容的图表:

Foo 的存储库:

C'-D'-E-F---G
       \   /
        H-I

Bar 的存储库:

...A-B-C-D-J-K---L
            \   /
             M-N

C,C' 和 D,D' 具有相同的内容,但版本号和版本不同。评论。

目标:

...A-B-C-D--E-F---G
          \  \   /
           \  H-I
            \
             J-K---L
              \   /
               M-N

我已经没有关于如何实现这一目标的想法了。我尝试了convert --splicemap splice.map [splice.map文件包含ED](没有做任何事情)。 Clone -f 设法将所有内容放入一个存储库中,但它们似乎是独立的树。在clone -f之后,我尝试了rebase --source E --dest D --detach,但它只是崩溃了:(

想法?

我知道改变历史记录将使任何人的存储库克隆无效,这不是问题所有用户都将从这一努力的结果中重新克隆。

Here's the situation: developer Foo created a hg repo from our svn repo. Foo's hg repo was only a shallow clone of the trunk in svn (no svn branches, tags, etc. and the history was incomplete [about 100 changesets]). Developer Bar did the same thing, but cloned the entire svn repo including the entire history, branches, tags, etc. Both Foo and Bar have done branchy development on their repositories.

There is a common SVN ancestor to both repositories, but each hg repo has a different version number for it. I would like to reparent Foo's changes from the common ancestor onto Bar's repo. Here's a diagram of what I'm looking for:

Foo's repo:

C'-D'-E-F---G
       \   /
        H-I

Bar's repo:

...A-B-C-D-J-K---L
            \   /
             M-N

C,C' and D,D' have the same content, but different version numbers & comments.

The goal:

...A-B-C-D--E-F---G
          \  \   /
           \  H-I
            \
             J-K---L
              \   /
               M-N

I've run out of ideas on how to make this happen. I tried convert --splicemap splice.map [splice.map file contained E D] (didn't do anything). Clone -f managed to get everything into one repo, but they appear to be independent trees. After clone -f, I tried rebase --source E --dest D --detach, but it just crashed :(

Ideas?

I'm aware altering the history will invalidate anyone's clone of the repositories, this is not a problem in this case. All users will be re-cloning from the result of this effort.

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

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

发布评论

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

评论(3

⊕婉儿2024-11-12 22:09:47

已解决!

我最初没有注意到的一件事是,我假定的共同祖先毕竟并不完全相同。在 Foo 的存储库的 svn->hg 转换期间,$ID$ 字符串被扩展,但在创建 Bar 的存储库时并未扩展。下面的步骤 1 是创建真正的共同祖先的简单修复。

以下步骤使我能够实现我的目标:

1- 确保假定的共同祖先(D 和 D')实际上是相同的。如果没有,请在 Bar 的存储库中为它们创建一个新的拼接点 (S)。在我的示例中,S 应该与 D' 的内容完全匹配。

    ...A-B-C-D--J-K---L
              \  \   /
               S  M-N

2- 修剪 Foo 存储库的历史记录,以删除重复的历史记录,包括 D',其中包含

    hg convert --splicemap TrimSplicemap Foo FooTrimmed

TrimSplicemap 内容:(其中 E 是 E 的完整哈希)

    E 0000000000000000000000000000000000000000

3- 使用 hg strip 以删除断开连接的冗余历史记录

    cd FooTrimmed
    hg strip C'

4- 再次使用 hg Convert 将 Foo 的剥离存储库拼接到 Bar 的存储库上,提交 'S'

    cd ../Bar
    hg convert --splicemap FooBarSplicemap ../FooTrimmed .

FooBarSplicemap 内容:(其中 E' 是 FooTrimmed 中 E 的新哈希值) ,S 是 S 的哈希值)

    E' S

应该可以了! :D

SOLVED!

One thing I didn't notice initially was that my presumed common ancestor wasn't exactly the same after all. During the svn->hg conversion of Foo's repo, the $ID$ strings were expanded, but were not in the creation of Bar's repo. Step 1 below was a simple fix to create a REAL common ancestor.

The following steps allowed me to accomplish my goal:

1- Ensure that the presumed common ancestor (D and D') are actually identical. If not, create a new splice point for them (S) in Bar's repo. S should exactly match the content of D' in my example.

    ...A-B-C-D--J-K---L
              \  \   /
               S  M-N

2- Trim the history of Foo's repo to remove the duplicate history, including D', with

    hg convert --splicemap TrimSplicemap Foo FooTrimmed

TrimSplicemap contents: (where E is the full hash of E)

    E 0000000000000000000000000000000000000000

3- Use hg strip to remove the disconnected, redundant history

    cd FooTrimmed
    hg strip C'

4- Use hg convert again to splice Foo's stripped repo onto Bar's repo at commit 'S'

    cd ../Bar
    hg convert --splicemap FooBarSplicemap ../FooTrimmed .

FooBarSplicemap contents: (where E' is the NEW hash for E in the FooTrimmed, and S is the hash of S)

    E' S

That should do it! :D

说不完的你爱2024-11-12 22:09:47

也许可以使用Mercurial 队列来完成此任务。

  1. 将存储库 Foo 中的每个变更集导入补丁队列。
  2. 转到 Bar 存储库。
  3. Bar 更新为作为共同祖先的变更集。
  4. 将补丁队列导入到 Bar 中。
  5. 应用补丁队列。

这将更改所有 Foo 补丁的提交 ID,但仍然允许您保留整个历史记录并将它们的开发存储库合并在一起。

You might be able accomplish this using Mercurial Queues.

  1. Import every changeset from repo Foo into a patch queue.
  2. Go to the Bar repo.
  3. Update Bar to the changeset that is the common ancestor.
  4. Import the patch queue into Bar.
  5. Apply the patch queue.

This would change the commit IDs of all the Foo patches, but still allow you to keep the entire history and merge their dev repos together.

安人多梦2024-11-12 22:09:47

我们今天在 IRC 中讨论了这个问题,我的建议是将两者拉入同一个存储库并让它有两个根。头部将完全符合您的要求,其余的并不重要。

如果你只是无法忍受(你想象人们比他们实际做的更多地使用历史/责备)那么我认为你的拼接图应该有:

E D

in in 因为你试图让 E 的父母成为 D (而不是 D' )

We talked about this today in IRC and my advice was to just pull both into the same repo and let it have two roots. The heads will be exactly as you want and the rest really doesn't matter.

If you just can't stomach that (you're imagining people use history/blame more than they really do) then I think your splicemap should have:

E D

in in since you're trying to get E's parent to be D (not D')

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