我正在开发一个已经用于大约十几个单独安装的Web数据库,其中大部分也是我管理的。每个安装都有相当多的本地配置和定制。刚从svn切换到mercurial,我想利用其分布式特性来跟踪本地修改。我已将每个已安装的服务器设置为自己的repo(并配置了apache以不提供.hg目录)。
我的困难在于开发树还包含本地配置,我想避免将其中的每一位放在未版本化的配置文件中。那么,如何设置以避免将本地配置传播到主仓库和已安装的副本?
示例:我有一个应该进行版本化和分发的长config.ini文件。 “干净”版本包含数据库连接参数的占位符,我不希望开发服务器的密码最终存储在已安装副本的存储库中。但是偶尔我会做出我需要传播的更改(例如,新的默认值)。在类似情况下有几个文件。
到目前为止,我能解决的最好方法是安装mq并将本地修改转换为补丁(实际上是两个补丁,具有逻辑上独立的变更集)。每次我想将常规变更集提交到 local repo时,我需要弹出所有补丁,提交修改并重新应用补丁。当我准备推送到主仓库时,我必须再次弹出补丁,推送并重新应用它们。这一切都令人费解并容易出错。
我能看到的唯一另一种选择是忘记推送并仅将更改集传播为补丁,这似乎是一个更糟糕的解决方案。有人可以建议更好的设置吗?我无法想象这是一个如此不同寻常的配置,但我还没有发现任何相关内容。
编辑:在对此处的建议进行跟进后,我得出结论,命名分支加rebase提供了一个简单且可行的解决方案。我以自己的答案的形式添加了一个描述。请看一下。
答案 0 :(得分: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 :(得分:1)
如果版本化模板和未版本化的本地副本的问题是模板的更改未使其成为本地副本,那么如何修改您的应用以使用未版本化的localconfig.ini
并回退到版本化config.ini
缺少参数。这样,可以将新的默认参数添加到config.ini
并传播到您的应用中。
答案 2 :(得分:1)
跟进了这里的建议,我得出结论,命名分支加rebase
提供了一个简单而可靠的解决方案。我一直在使用以下方法已经有一段时间了,效果非常好。基本上,围绕局部变化的历史被分成命名分支,可以使用rebase轻松地重新排列。
我使用分支local
来获取配置信息。当我的所有回购支持阶段时,我将标记当地分支secret
;但是这个方法没有它。 local
取决于default
,但默认值不依赖于local
,因此可以单独推送(使用hg push -r default
)。以下是它的工作原理:
假设开发的主线位于default
分支。 (你可以有更多的分支;这是为了具体)。有一个主(稳定)回购,不包含密码等。:
---o--o--o (default)
在每个已部署(非开发)的克隆中,我创建了一个分支local
并将所有本地状态提交给它。
...o--o--o (default)
\
L--L (local)
来自上游的更新将始终处于默认状态。每当我提取更新时,我会将它们合并到local
(n
是一系列新更新):
...o--o--o--n--n (default)
\ \
L--L--N (local)
本地分支跟踪default
的演变,如果出现问题,我仍然可以返回旧配置。
在开发服务器上,我从相同的设置开始:local
分支,其配置设置如上所述。永远不会被推动。但是在local
的尖端,我创建了第三个分支dev
。这是新发展的地方。
...o--o (default)
\
L--L (local)
\
d--d--d (dev)
当我准备将一些功能发布到主存储库时,我首先将整个dev
分支重新绑定到default
的提示:
hg rebase --source "min(branch('dev'))" --dest default --detach
上一棵树变为:
...o--o--d--d--d (default)
\
L--L (local)
重新定位的变更集现在属于分支default
。 (使用功能分支,将--keepbranches
添加到rebase命令以保留分支名称)。新功能在local
中不再包含任何祖先,我可以使用push -r default
发布它们,而无需拖动本地修订版。 (永远不要从local
合并到 default
;只能从另一种方式合并。如果您在推送时忘记说-r default
,没问题:您的推送被拒绝,因为它会增加一个新头。
在开发服务器上,我将重新定位的转换合并到local
,就好像我只是将它们拉出来一样:
...o--o--d--d--d (default)
\ \
L--L-----N (local)
我现在可以在dev
之上创建一个新的local
分支,然后继续开发。
这具有我可以在版本控制的配置设置上开发的好处;我不需要弄乱补丁;以前的配置阶段保留在历史记录中(如果我的Web服务器在更新后停止工作,我可以更新回配置的版本);当我准备发布更改时,我只会改变一次。如果修订与本地配置更改发生冲突,则重新定位和后续合并可能会导致冲突;但如果这种情况发生,那么当合并设施可以帮助解决它们时,它们会更好。
答案 3 :(得分:0)
1 Mercurial 有(后续评论)有选择性(基于字符串)提交 - 请参阅记录扩展
使用MQ Extension可以轻松接收 版本化公共文件 本地更改(我一直用于站点配置)。你对MQ的头痛每次我想将常规变更集提交到本地仓库时,我 需要弹出所有补丁,提交修改并重新应用 补丁。当我准备推送到主回购时,我必须再次弹出 修补程序,推送并重新应用它们。
是因为没有完善的工作流程和(某些)误解。如果你想要没有MQ补丁的提交 - 不要手工完成。为commit添加别名,qop -all + commit并仅使用此新命令。当你推动时,你可能不担心MQ状态 - 你从repo推动变更集,而不是WC状态。通过预提交钩子检查内容,也可以通过保护无别名。
3您可以尝试使用LocalBranches扩展,其中您的本地更改存储在本地分支内(并在更改时合并分支) - 与MQ相比,我发现这种方式更麻烦