我在a comment中提到了基本流程。从本质上讲,您需要原始的 Mercurial 存储库,其中包含您发送到原始 Bitbucket 服务器以进行 PR 的变更集。
(注意:我实际上并没有这样做。这都是理论上的。不过,理论非常简单。同样的技术也适用于从 CVS 或 SVN 或 Perforce 的转换。关键是构建一个临时的具有正确提交的 Git 存储库,该提交导致并包含一组要复制的 PR 提交。然后,我们将仅将 PR 提交复制到链接到 GitHub 存储库的 Git 存储库。)
执行此操作的最佳(或最短或最简单)方法可能会有所不同,具体取决于一些细节。但是,据推测,您拥有或至少可以克隆整个原始 Mercurial 存储库及其来自 bitbucket 的拉取请求。这将为您提供一个完整的、自包含的 Hg 存储库,其中包含一系列变更集,包括最初转换为 Git 的所有变更集,以及此后成为您 PR 一部分的变更集。
您现在可以通过任何您喜欢的方式将整个内容转换为一个新 Git 存储库。这个 Git 存储库将或多或少地对每个原始 Mercurial 变更集进行一次提交。 (“或多或少”发生在您故意不转换某些 hg 提交和/或您有 hg 标签的地方,这会导致新提交,这些新提交被转换为不使用提交的 Git 标签。一些细节是可能取决于您的转换软件。)
这个新的 Git 存储库可能与 GitHub 上的完全无关,与原始转换到 Git 的提交哈希不同。或者,如果转换很简单,当你构建这个新的 Git 存储库时,它实际上会使用原始的哈希 ID,因此是强相关的!
如果它真的有那么密切的关系,那么问题实际上就消失了。只需为这个 Git 存储库设置一个远程,即 GitHub 存储库(或其分支)和 git push 那里的其他提交,并像往常一样进行 GitHub PR。
如果它不密切相关,那么您最可能应该做的——这似乎是最简单的方法——是使用git cherry-pick。这里涉及到很多存储库,所以让我们使用一些简单的单字母名称来命名每个存储库:
-
Gmain 是 GitHub 存储库(或您的 fork),您要在其中创建新 PR。
李>
Glocal 是您自己计算机上的 Gmain 的克隆。 (我会简称为“您的笔记本电脑”,即使您实际上并没有使用笔记本电脑,以将其与各种服务器上的许多 Git 存储库区分开来。)
R0 是您的 Mercurial 存储库,其中包含您已经拥有或从 Bitbucket 上的 PR 重新克隆的额外提交。 p>
Rg 是您转换为 Git 后的存储库。这个存储库可以直接存在于您的笔记本电脑上。请注意,它在某个分支上有新的提交,几乎——但在这种情况下不完全——准备好成为git pushed。问题是这些提交的历史与 Gmain 中的历史无关。
在 Glocal 中,在您的笔记本电脑上,您现在将使用 git remote add 为 Rg:
git remote add recoverer <url>
这只是你笔记本电脑上Rg的路径。 (如果你愿意,你可以把file:///放在它前面,但如果你不这样做——如果你直接使用Rg的完整路径——你的Git不使用额外磁盘空间会更聪明。如果由于某种原因 Rg 在某个服务器上,请使用允许您的 Git 访问该服务器的 URL,并且您的 Git将需要分配新的本地磁盘空间来复制所有提交,一段时间。)
现在运行:
git fetch recoverer
这将用来自 Rg 的提交(整个历史)填充您的 Glocal,创建远程-recoverer/origin、recoverer/develop 等形式的跟踪名称。您想要的提交——除了它们不正确的历史链接——现在在一个远程跟踪名称上。具体而言,我将其称为recoverer/pr123,但实际名称取决于您在 R0 中使用的分支或书签名称,该名称由您的转换软件创建时Rg.
请注意,在分支recoverer/pr123 上的这些提交之前有许多(数十、数百、数千等)提交,这些提交也在recoverer/pr123 上。 Git,在其对提交在分支上意味着什么的奇怪概念中,通常在多个分支上提交。包含提交的一组分支动态变化随着时间的推移!这与 Mercurial 非常不同,在 Mercurial 中,提交礼貌地保留在其原始分支中。因此,您现在的目标是复制 only 在recoverer/pr123 上的提交,而不是那些 和 在 recoverer/master 或任何其他分支上的提交出现在。
您可以通过它们的哈希 ID 找到这些提交,一次一个,或者您可以找出哪些名称可以排除它们。例如,如果git log recoverer/master..recoverer/pr123 显示了正确的提交集,则名称recoverer/master 可以排除不需要的 提交。您将通过一种或另一种方式运行git log recoverer/pr123,可能在前面加上一些排除名称,以验证您是否获得了正确的提交集以进行复制。
找到要为您的 PR 复制的提交 - 无论是通过单个哈希 ID 还是通过此类名称,您现在只需运行:
git checkout <branch>
(其中 branch 是您要将这些提交复制到的位置到,如果您愿意,可以是一个新分支)然后:
git cherry-pick <hashes-or-string>
例如,git cherry-pick recoverer/master..recoverer/pr123。 Git 现在将尝试复制——或者用 Mercurial 术语,graft——这些提交到当前分支。新提交将进行与原始提交相同的更改,但将是一个新的历史块——一组新的提交——从您在git checkout <em>branch</em> 步骤中签出的提交开始。
一切顺利后,您可以像往常一样 git push origin 并像往常一样发出 GitHub 拉取请求。您也可以git remote remove recoverer 删除 Glocal 中的所有 recoverer/* 名称,并从 Glocal 中删除链接> 到 Rg,你可以删除 Rg 本身。 (您可以在完成挑选后随时执行所有这些操作。)如果 Git 在 Glocal 中与 Rg 共享内容,一旦你删除了Rg,磁盘空间就会被释放。如果没有,Git 最终将“垃圾收集”额外的磁盘空间,因为它与 Rg 的链接已经消失。