2

我正在开发一个 Web 数据库,该数据库已经用于十几个单独的安装,其中大部分由我自己管理。每个安装都有相当多的本地配置和定制。刚刚从 svn 切换到 mercurial,我想利用它的分布式特性来跟踪本地修改。我已将每个已安装的服务器设置为自己的存储库(并将 apache 配置为不为 .hg 目录提供服务)。

我的困难是开发树还包含本地配置,我想避免将它的每一点都放在未版本化的配置文件中。那么,我该如何设置以避免将本地配置传播到主存储库和已安装的副本?

示例:我有一个很长的 config.ini 文件,应该对其进行版本控制和分发。“干净”版本包含数据库连接参数的占位符,我不希望开发服务器的密码最终出现在已安装副本的存储库中。但有时我会做出一些我确实需要传播的更改(例如,新的默认值)。有几个文件处于类似情况。

到目前为止,我能做的最好的事情是安装 mq 并将本地修改变成一个补丁(实际上是两个补丁,具有逻辑上独立的变更集)。每次我想向本地存储库提交常规变更集时,我都需要弹出所有补丁、提交修改并重新应用补丁。当我准备好推送到主仓库时,我必须再次弹出补丁,推送并重新应用它们。这一切都令人费解且容易出错。

我能看到的唯一另一种选择是忘记推送,只将变更集作为补丁传播,这似乎是一个更糟糕的解决方案。有人可以建议更好的设置吗?我无法想象这是一个如此不寻常的配置,但我还没有找到任何关于它的信息。

编辑:在跟进这里的建议之后,我得出的结论是,命名分支加上 rebase 提供了一个简单且可行的解决方案。我以自己的答案的形式添加了描述。请看一下。

4

4 回答 4

2

从您的评论来看,您似乎已经熟悉处理此问题的最佳实践:版本化配置模板,并保持实际配置未版本化。

但是由于您对该解决方案不满意,因此您可以尝试另一种解决方案:

Mercurial 2.1 引入了Phases的概念。阶段是变更集元数据,将其标记为“秘密”、“草稿”或“公共”。通常,这些元数据由 mercurial 及其扩展自动使用和操作,而用户无需知道它。

但是,如果您创建了一个1234永远不想推送到其他存储库的变更集,您可以通过手动将其标记为秘密来强制执行此操作,如下所示:

hg phase --force --secret -r 1234

如果您随后尝试推送到另一个存储库,它将被忽略并出现以下警告:

pushing to http://example.com/some/other/repository
searching for changes
no changes found (ignored 1 secret changesets)

该解决方案允许您

  1. 版本本地配置更改
  2. 防止这些更改被意外推送
  3. 将您的本地更改与您引入的其他更改合并

当然,最大的缺点是您无法推送在此秘密变更集之上所做的更改(因为这会推动秘密变更集)。您必须先重新调整任何此类更改,然后才能推送它们。

于 2012-03-04T13:41:28.483 回答
1

如果版本化模板和非版本化本地副本的问题在于模板的更改不会进入本地副本,那么如何修改您的应用程序以使用非版本localconfig.ini化并回退到config.ini缺少参数的版本化。通过这种方式,可以将新的默认参数添加到您的应用程序中config.ini并传播到您的应用程序中。

于 2012-03-04T16:49:36.507 回答
1

跟进这里的建议后,我得出结论,命名分支加上rebase提供了一个简单可靠的解决方案。我已经使用以下方法有一段时间了,效果很好。基本上,围绕本地更改的历史被分成命名的分支,这些分支可以很容易地用 rebase 重新排列。

我使用分支local获取配置信息。当我所有的 repos 都支持 Phases 时,我会标记本地分支secret;但是没有它,该方法也有效。local依赖default,但默认不依赖,local因此可以独立推送(使用hg push -r default)。以下是它的工作原理:

  1. 假设开发的主线在default分支。(你可以有更多的分支;这是为了具体化)。有一个不包含密码等的主(稳定)存储库:

    ---o--o--o   (default)
    
  2. 在每个部署的(非开发)克隆中,我创建一个分支local并将所有本地状态提交给它。

    ...o--o--o   (default)
              \
               L--L    (local)
    
  3. 来自上游的更新将始终默认。每当我提取更新时,我都会将它们合并到localn是一系列新更新):

    ...o--o--o--n--n    (default)
              \     \
               L--L--N     (local)
    

    本地分支跟踪 的演变default,如果出现问题,我仍然可以返回旧配置。

  4. 在开发服务器上,我从相同的设置开始:具有local上述配置设置的分支。这永远不会被推动。但在local我创建第三个分支的最后,dev. 这就是新的发展发生的地方。

    ...o--o   (default)
           \
            L--L    (local)
                \
                 d--d--d     (dev)
    
  5. 当我准备将一些功能发布到主存储库时,我首先将整个dev分支重新定位到default

    hg rebase --source "min(branch('dev'))" --dest default --detach
    

    之前的树变成:

    ...o--o--d--d--d   (default)
           \
            L--L    (local)
    

    重新设置的变更集现在属于 branch default。(使用功能分支,添加--keepbranches到 rebase 命令以保留分支名称)。新功能在 中不再有任何祖先,我可以在不拖拽本地修订的情况下local发布它们。push -r default(永远不要从local into default合并;反之亦然)。如果你在推送时忘记说-r default,没问题:你的推送被拒绝,因为它会添加一个新的头部。

  6. 在开发服务器上,我将重新定位的转速合并local为就像我刚刚拉出它们一样:

    ...o--o--d--d--d   (default)
           \        \
            L--L-----N    (local)
    
  7. 我现在可以dev在 之上创建一个新分支local,并继续开发。

这具有我可以在受版本控制的配置设置上开发的好处;我不需要弄乱补丁;以前的配置阶段仍保留在历史记录中(如果我的网络服务器在更新后停止工作,我可以更新回配置的版本);并且当我准备好发布更改时,我只变基一次。如果修订与本地配置更改发生冲突,则变基和后续合并可能会导致冲突;但如果这种情况发生,最好在合并设施可以帮助解决它们时发生。

于 2012-04-03T07:30:57.327 回答
0

1 Mercurial(跟进评论)选择性(基于字符串)提交 - 请参阅记录扩展

2使用 MQ 扩展可以很容易地接收版本化公共文件中的本地更改(我一直为站点配置这样做)。您对 MQ 的头疼

每次我想向本地存储库提交常规变更集时,我都需要弹出所有补丁、提交修改并重新应用补丁。当我准备好推送到主仓库时,我必须再次弹出补丁,推送并重新应用它们。

是未完善的工作流程和(某些)误解的结果。如果您想在没有 MQ 补丁的情况下提交 - 不要手动执行。为提交添加别名,其中 qop -all + commit 并仅使用此新命令。当你推送时,你可能不用担心 MQ 状态——你从 repo 推送变更集,而不是 WC state。本地 repo 也可以通过 pre-commit hook 检查内容在没有别名的情况下进行保护。

3 您可以尝试 LocalBranches 扩展,您的本地更改存储在本地分支中(并在更改时合并分支) - 与 MQ 相比,我发现这种方式更麻烦

于 2012-03-04T15:57:02.777 回答