问题 当Mercurial导入的补丁失败时该怎么办?


从服务器存储库中取出后,我从本地工作仓库导出了一堆更改集。为了确保补丁工作,我从服务器克隆了一个新的repo,我尝试应用变更集。不幸的是,导入失败了:

applying G:\OSS\premake-dev\premake-dev_rev493.patch
unable to find 'src/host/scripts.c' for patching
3 out of 3 hunks FAILED -- saving rejects to file src/host/scripts.c.rej
patching file src/base/api.lua
patching file src/host/scripts.c
patching file src/tools/bcc.lua
file tests/test_bcc.lua already exists
1 out of 1 hunks FAILED -- saving rejects to file tests/test_bcc.lua.rej
patching file tests/premake4.lua
patching file tests/test_bcc.lua
abort: patch failed to apply

[command interrupted]

我知道失败的原因,这是由于最新的变更集中不再存在已删除的源文件。但我不确定如何修复我的补丁,以便它可以干净地应用于当前的服务器存储库。

我对Mercurial很新,所以使用的一些术语我不会熟悉。另请注意,我没有对Hg服务器存储库的写访问权限。因此,为了获得我的变更集,我必须将其作为补丁导出并将其提交给维护者。


10488
2018-01-04 08:56


起源

如何更新回到修补程序构建的变更集,应用它,提交它,然后将其与头部合并? - Lasse Vågsæther Karlsen
@Lasse感谢您的建议。我会试一试并报告。这可能值得作为答案发布,因此更容易上传 - greatwolf


答案:


我必须承认没有经常使用补丁,所以这可能不是正确的工作流程,但我会尝试,如果我在那种情况下是将补丁应用于它最初基于的变更集。

换句话说,听起来你有以下情况:

                    +-- you're here
                    |
                    v
1---2---3---4---5---6
     \
      \
       X <-- patch was built to change 2 to X

我会做什么,只要我知道补丁最初所基于的变更集,将更新回更改集,应用补丁,这将添加另一个头,然后将其合并到您的存储库的提示。

执行这些操作后,存储库应如下所示:

                        +-- you're here
                        |
                        v
1---2---3---4---5---6---8
     \                 /
      \               /
       7-------------/
       ^
       |
       +-- this is the changeset you committed after applying the patch

现在,以不同的方式。

使用补丁是唯一的方法吗?使用Mercurial时,一种常见的方法是设置自己的存储库,一个fork,最初包含中央存储库的完整克隆,但您具有提交访问权限。

因此,您可以将新的更改集提交到自己的克隆中。

如果中央存储库在您克隆后添加了新的更改集,则在某些时候将其从克隆中拉入并进行合并。

然后,当您满意时,向中央存储库的维护者发出拉取请求,告诉他们“嘿,我有一些更改,你可以从我的克隆中取出它们:http:// ......” 。

通过这种方式,这些维护人员很容易将所有内容都包含在内,因为您已经为他们完成了所有艰苦的工作。

这意味着您有两个这样的存储库:

central: 1--2

clone:   1--2

你添加你的工作:

central: 1--2

clone:   1--2--3

他们添加了一些变更集:

central: 1--2--3--4--5--6

clone:   1--2--3

然后你拉:

central: 1--2--3--4--5--6

clone:   1--2--4--5--6--7
             \
              \
               3  <-- this is your changeset

然后你合并:

central: 1--2--3--4--5--6

clone:   1--2--4--5--6--7--8
             \            /
              \          /
               3--------/

如果维护者现在从您那里获取,他们将获得完全相同的历史记录到他们的存储库中。

还有一些对rebase的支持,这意味着你不必拉和合并,但维护者会发出“pull with rebase”命令,实际上将你的变更集从其当前位置重新定位到他们的存储库中的新位置,这看起来像这样:

central: 1--2--3--4--5--6---7
                            ^
clone:   1--2--3            |  relocated here
               |            |
               +------------+

这只有在没有合并冲突的情况下才有效。拉动和合并的方法对他们来说是最好的,因为你做了所有艰苦的工作,他们只需要验证代码是他们想要的。

有关分叉的更多信息,请查看Tekpub在CodePlex和Mercurial上的视频,在这里: Tekpub:7 - Mercurial与CodePlex,寻求在21:15左右开始分叉。

请注意,“fork”基本上只是一个克隆,在CodePlex中分叉的方式是它自动在您自己的帐户上设置克隆,并向原始维护者发送拉取请求,但是如果您在Bitbucket上创建自己的帐户或CodePlex或其他什么,在那里发布您的克隆,只需向维护者发送一封包含您的存储库URL的电子邮件,这就是它的全部内容。


13
2018-01-04 10:02



感谢全面的写作。在应用补丁之前将我的头部更新到早期的设置让我大部分时间。视频+1,非常有用,让一些事情变得更清晰。我想我会在bitbucket试试这个forking方法。 - greatwolf
“嘿,我有一些改变,你可以从我的克隆中拉出来:http:// ......”。  获取我的仓库的URL的过程是否很困难?我想我可以将它上传到服务器主回购。 - Noumenon
要使用url从某处“拉”,您需要托管存储库的某个位置。您可以在本地托管它们 hg serve 但是你可能不得不处理本地IP地址,防火墙和端口等。 - Lasse Vågsæther Karlsen


就我而言,我失败了 hg import 与行结尾有关。解决方案是把它放在我的 〜/ .hgrc 文件:

[patch]
eol = auto

2
2018-01-10 09:28



当Outlook选择从我的电子邮件补丁中删除“额外”行结尾时,这也发生在我身上。单击还原选项有效。 - Noumenon