如何使用 Mercurial 子存​​储库来共享组件和依赖项?

2023-11-25

我们使用 C# 开发 .NET 企业软件。我们正在寻求改进我们的版本控制系统。我以前使用过mercurial,并且一直在我们公司尝试使用它。然而,由于我们开发企业产品,我们非常关注可重用的组件或模块。我一直在尝试使用 Mercurial 的子存储库来管理组件和依赖项,但遇到了一些困难。以下是源代码控制/依赖管理的基本要求:

  1. Reusable components
    1. 按源共享(用于调试)
    2. 依赖于第三方二进制文件和其他可重用组件
    3. 可以在消费产品的环境中进行开发并致力于源代码控制
  2. Dependencies
    1. 产品依赖于第三方二进制文件和其他可重用组件
    2. 依赖项有自己的依赖项
    3. 应通知开发人员依赖项中的版本冲突

这是我一直在使用的 Mercurial 的结构:

可重复使用的组件:

SHARED1_SLN-+-docs
            |
            +-libs----NLOG
            |
            +-misc----KEY
            |
            +-src-----SHARED1-+-proj1
            |                 +-proj2
            |
            +-tools---NANT

第二个可重用组件,消耗第一个:

SHARED2_SLN-+-docs
            |
            +-libs--+-SHARED1-+-proj1
            |       |         +-proj2
            |       |
            |       +-NLOG
            |
            +-misc----KEY
            |
            +-src-----SHARED2-+-proj3
            |                 +-proj4
            |
            +-tools---NANT            

消耗这两种成分的产品:

PROD_SLN----+-docs
            |
            +-libs--+-SHARED1-+-proj1
            |       |         +-proj2
            |       |
            |       +-SHARED2-+-proj3
            |       |         +-proj4
            |       |
            |       +-NLOG
            |
            +-misc----KEY
            |
            +-src-----prod----+-proj5
            |                 +-proj6
            |
            +-tools---NANT

Notes

  1. 回购协议采用大写字母格式
  2. 所有子存储库都被假定为子存储库
  3. 第 3 方(二进制)库和内部(源)组件都是位于 libs 文件夹中的子存储库
  4. 第 3 方库保存在单独的 Mercurial 存储库中,以便使用项目可以引用库的特定版本(即旧项目可能引用 NLog v1.0,较新项目可能引用 NLog v2.0)。
  5. 所有 Visual Studio .csproj 文件都位于第 4 级(proj* 文件夹),允许对依赖项进行相对引用(即 ../../../libs/NLog/NLog.dll 对于引用 NLog 的所有 Visual Studio 项目)
  6. 所有 Visual Studio .sln 文件都位于第二级(src 文件夹),以便在将组件“共享”到使用组件或产品时不包含它们
  7. 开发人员可以按照自己认为合适的方式自由组织源文件,只要源是使用 Visual Studio 项目的 proj* 文件夹的子级(即 proj* 文件夹可以有 n 个子级,包含各种源/资源)
  8. 如果 Bob 正在开发 SHARED2 组件和 PROD1 产品,那么他在 PROD1_SLN 存储库中更改 SHARED2 源(例如属于 proj3 的源)并提交这些更改是完全合法的。我们不介意有人在消费项目的背景下开发库。
  9. 内部开发的组件(SHARED1 和 SHARED2)通常按源包含在使用项目中(在 Visual Studio 中添加对项目的引用而不是浏览到 dll 引用)。这允许增强调试(单步进入库代码),允许 Visual Studio 管理何时需要重建项目(当修改依赖项时),并允许在需要时修改库(如上面的注释中所述)。

问题

  1. 如果 Bob 正在处理 PROD1,而 Alice 正在处理 SHARED1,那么 Bob 如何知道 Alice 何时向 SHARED1 提交更改。目前,使用 Mercurial,Bob 被迫在每个子存储库中手动拉取和更新。如果他从 PROD_SLN 存储库推送/拉取到服务器,他永远不会知道子存储库的更新。这在以下位置进行了描述水星维基。当 Bob 从服务器提取最新的 PROD_SLN 时,如何通知他子存储库的更新?理想情况下,他应该收到通知(最好在拉取期间),然后必须手动决定他想要更新哪个子存储库。

  2. 假设 SHARED1 引用 NLog v1.0(mercurial 中的 commit/rev abc),SHARED2 引用 Nlog v2.0(mercurial 中的 commit/rev xyz)。如果 Bob 在 PROD1 中吸收这两个组件,则应该让他意识到这种差异。虽然从技术上讲,Visual Studio/.NET 允许 2 个程序集引用不同版本的依赖项,但我的结构不允许这样做,因为对于依赖于 NLog 的所有 .NET 项目,NLog 的路径都是固定的。 Bob 如何知道他的两个依赖项存在版本冲突?

  3. 如果 Bob 正在为 PROD1 设置存储库结构并希望包含 SHARED2,那么他如何知道 SHARED2 需要哪些依赖项?根据我的结构,他必须手动克隆(或在服务器上浏览)SHARED2_SLN 存储库,然后查看 libs 文件夹,或者查看 .hgsub 文件以确定他需要包含哪些依赖项。理想情况下,这将是自动化的。如果我在我的产品中包含 SHARED2,SHARED1 和 NLog 也会自动包含在内,如果与其他依赖项存在版本冲突,则会通知我(请参阅上面的问题 2)。

更大的问题

  1. Mercurial 是正确的解决方案吗?

  2. 有没有更好的水银结构?

  3. 这是子存储库的有效用途吗(即 Mercurial 开发人员标记为subrepos作为最后手段的功能)?

  4. 使用 Mercurial 进行依赖管理是否有意义?我们可以使用另一个工具进行依赖关系管理(也许是内部 NuGet feed?)。虽然这对于第 3 方依赖项来说效果很好,但它确实会给内部开发的组件带来麻烦(即,如果它们是积极开发的,开发人员将不得不不断更新源,我们将不得不在内部为它们提供服务,并且不允许由使用项目修改的组件(注释 8 和问题 2)。

  5. 对于企业 .NET 软件项目,您有更好的解决方案吗?

参考

我读过几个SO问题并发现this one能够提供帮助,但是接受的答案建议使用专用工具来处理依赖关系。虽然我喜欢这种工具的功能,但它不允许从消费项目修改和提交依赖项(请参阅更大的问题 4)。


这可能不是您正在寻找的答案,但我们最近有 Mercurial 新手用户使用子存储库的经验,我一直在寻找机会传递我们的经验......

总结来说,根据经验我的建议是:无论 Mercurial 子存​​储库多么吸引人,都不要使用它们。相反,找到一种方法来并排放置目录,并调整构建来应对这种情况。

无论将子存储库中的修订与父存储库中的修订结合在一起似乎很有吸引力,但它在实践中行不通。

在转换的所有准备过程中,我们收到了来自多个不同来源的建议,认为子存储库很脆弱并且实施得不好 - 但我们还是继续前进,因为我们希望在存储库和子存储库之间进行原子提交。这些建议——或者我对它的理解——更多地谈论了原则而不是实际后果。

直到我们使用 Mercurial 和子存储库后,我才真正正确地理解了这些建议。这里(凭记忆)是我们遇到的各种问题的示例。

  • 您的用户最终将与更新和合并过程作斗争。
  • 有些人会更新父仓库而不是子仓库
  • 有些人会从子存储库推送,ang .hgsubstate 将不会更新。
  • 您最终将“丢失”在子存储库中所做的修订,因为有人会在合并后设法使 .hgsubstate 处于错误状态。
  • 有些用户会遇到 .hgsubstate 已更新但子存储库尚未更新的情况,然后您会收到非常神秘的错误消息,并且会花费很多时间尝试弄清楚发生了什么。
  • 如果您对版本进行标记和分支,则如何为父存储库和子存储库做好此操作的说明将长达数十行。 (我什至有一位友善、温顺的 Mercurial 专家帮助我编写说明!)

所有这些事情对于专家用户来说已经够烦人的了——但是当你向新手用户推出 Mercurial 时,它们就是一场真正的噩梦,并且是浪费大量时间的根源。

因此,在投入大量时间来进行子存储库转换后,几周后我们将子存储库转换为存储库。因为我们在通过 .hgsubstate 引用子存储库的转换中有大量历史记录,所以它给我们留下了更复杂的东西。

我只希望我能早点真正理解所有建议的实际后果,例如在 Mercurial 的最后的手段的特点 page:

但我需要管理子项目!

再说一次,不要那么确定。像 Mozilla 这样具有大量依赖项的重要项目在不使用子存储库的情况下也能正常工作。大多数小型项目在不使用子存储库的情况下几乎肯定会更好。


编辑:思考shell 仓库

有了免责声明,我对他们没有任何经验......

不,我不认为他们中有很多人是这样的。您仍在使用子存储库,因此所有相同的用户问题都适用(当然,除非您可以为每个步骤提供包装器脚本,以消除人类提供处理子存储库的正确选项的需要。)

另请注意,您引用的 wiki 页面确实列出了 shell 存储库的一些具体问题:

  • 过于严格地跟踪project/和somelib/之间的关系
  • 无法检查或推送项目/如果某些lib/源代码库变成
  • 不可用 缺乏对递归 diff、log 和 的明确支持
  • 提交的状态递归性质令人惊讶

编辑 2 - 进行试用,让所有用户参与

当多个用户开始提交、拉取和推送时,我们才真正开始意识到我们遇到了问题——包括对子存储库的更改。对我们来说,现在回应这些问题已经太晚了。如果我们早点认识他们,我们的反应就会更容易、更简单。

所以在这一点上,我认为我能提供的最好建议就是推荐你在布局刻板之前对项目布局进行试运行.

我们等到全面试验时已经太晚了,无法进行更改,即使这样,人们也只在父存储库中进行更改,而不是子存储库 - 所以我们仍然没有看到全貌,直到为时已晚。

换句话说,无论您考虑什么布局,都可以在该布局中创建一个存储库结构,并让很多人进行编辑。尝试将足够的真实代码放入各种存储库/子存储库中,以便人们可以进行真正的编辑,即使它们将是一次性的。

可能的结果:

  • 您可能会发现一切正常 - 在这种情况下,您将花费一些时间来获得确定性。
  • 另一方面,您可能会比花时间尝试找出结果更快地发现问题
  • 您的用户也会学到很多东西。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Mercurial 子存​​储库来共享组件和依赖项? 的相关文章

  • 在不支持线程的程序加载的共享库中使用 C++11 多线程

    我目前正在尝试在共享库中使用 C 11 多线程 该库加载到 Linux 上的主程序 用 C 编写 中 这是一个大型模拟程序的一部分 我无法更改有关库加载的任何内容或更改一般的主程序 主程序是用 gcc 4 1 2 编译的 我没有它的源代码
  • Jenkins 共享库:“java.lang.NoSuchMethodError:没有这样的 DSL 方法”

    我正在尝试通过 Jenkinsfile 和共享库创建 Jenkins 管道 我通过 Web UI 创建了一个作业来获取 Jenkinsfile 它工作正常 但是 共享库内容似乎无法被 Jenkins 识别 下面是 Jenkinsfile 和
  • Mercurial:如何管理公共/共享代码

    我将 Mercurial 用于个人用途 并出于各种原因考虑将它作为 SVN 的替代品用于某些分布式项目 我已经习惯将它用于自包含项目 并且可以看到各种共享选项 但是我还没有找到任何关于管理公共库的指南 以与 subversion 中的外部提
  • 如何让 mod_wsgi 在 Mac 上运行?

    几个小时以来 我一直在尝试在 Mac 上安装最新版本的 mod wsgi 3 3 我使用的是 Snow Leopard 并且有系统附带的 Apache Apache 2 2 15 和 Python 2 6 1 r261 67515 版本 我
  • 协调多个依赖的 Mercurial 存储库版本的推荐方法?

    好吧 经过几个小时的阅读和反复试验 它终于击中了我 Mercurial 并不真正想做 SubRepos 至少不想与 TortoiseHg 和 Bitbucket 一起使用 如果我错了 并且您不希望对类似于 当然它有效 您没有阅读官方文档吗
  • 如何存储和计算版本控制历史记录?

    考虑这个简单的 python 代码 它演示了一个非常简单的字典版本控制设计 def build current history current for action key value in history assert action in
  • 如何在 IIS 上设置 Mercurial 和 hgweb?

    我一直在寻找关于如何让 hgweb 在 IIS 上工作的不错的说明 但我没有发现太多有价值的信息 There s 这个 一步一步 https www mercurial scm org wiki HgWebDirStepByStep在 Me
  • PyCharm和源代码控制,.idea目录,提交还是不提交,这就是问题

    我开始了新的PyCharm http www jetbrains com pycharm 项目并希望对其进行版本控制水银 http mercurial selenic com 项目目录中有一个 idea 目录 其中包含以下文件 以及我对是否
  • 如何让 Heroku 安装 devDependency?

    我希望 Heroku 在推送应用程序后构建我的应用程序 这样我就不必每次进行更改时都将构建文件夹向上推送 然而 Heroku 仅安装来自package json和 grunt 我的构建工具 及其所有组件都在devDependencies 我
  • 使用 Mercurial 自动构建的版本编号

    我们最近从 SVN 切换到 Mercurial 我们还设置了一个 CruiseControl NET 来运行自动构建 它从源代码控制中获取最新信息并构建应用程序 在用于自动构建的 CruiseControl NET 仪表板中 我们希望显示版
  • 在共享库中不使用 PLT 的情况下调用另一个目标文件中的函数?

    我有两个汇编代码 code1 s and code2 s我想从这两个构建一个可重定位 使用 fPIC 开关 共享库 I want code2 s调用一个函数 名为myfun1 其定义在code1 s 当我使用call myfun1 PLT
  • 为什么GCC编译的应用程序总是包含_mcount符号?

    库并不总是包含 mcount 符号 但应用程序包含 您可以使用 gobjdump 或 nm 实用程序验证这一点 我读过 mcount 用于实现分析 但即使禁用分析并启用优化 O2 该符号仍然存在 它还有其他额外的用途吗 更新 我使用的是 S
  • hg 语法的作用是什么:提交 A 是否可以从提交 B“到达”

    我的存储库的历史非常复杂 我经常发现自己想知道过去的某个提交是否 在 或 可从 某个修订 通常是我的头脑之一 到达 我该怎么做呢 您可以使用转速集语法 http selenic com hg help revsets 假设您想询问修订版 4
  • 如何在运行“更新”之前查看存储库中的文件

    I run hg pull这向我的存储库添加了新的更改 在使用新更改更新我的工作目录之前 我想查看这些新文件 更改 我相信我使用的 SVNsvn st u但在 Mercurial 中是如何完成的呢 在拉动之前 您可以使用 hg incomi
  • 是什么让 DVCS 中的合并变得如此简单?

    我读于乔尔谈软件 http www joelonsoftware com items 2010 03 17 html 通过分布式版本控制 分布式部分实际上不是 最有趣的部分 有趣的是 这些 系统根据变化来思考 而不是 就版本而言 and a
  • 使用 xerces 链接 DLL 会给出未定义的符号

    我正在使用 cygwin 创建一个共享库 DLL 它使用 Xerces 当我从主应用程序调用 xercesc 函数时 一切都很好 但是当我尝试将一些代码放入库中时 我会得到 xerxesc 定义的所有静态内容的未定义符号 例如 std st
  • 如何配置 VS Code 以便能够单步执行调试 Python 脚本时加载的共享库 (.so)?

    从命令行使用 gdb 我可以在加载共享库时中断 知道我有共享库的源代码 如何在 VS Code 中获得相同的行为 对我来说 它以某种方式起作用 这是我的设置 Ubuntu 18 04 调试我从 Python3 加载的 C 共享库 更具体地说
  • TFS 2010 跨团队项目分支 - 最佳实践

    我在了解如何根据 TFS Ranger 团队提供的最佳实践配置 TFS 时遇到问题 问题是这样的 我的公司有多种产品使用共享的通用代码库 gt Core gt gt Main Source Parent Branch gt gt Produ
  • 如何解决这一 Mercurial 冲突?

    我对 Mercurial 和 Python 感到沮丧 因为它们让简单的事情变得困难 我有一个微不足道的冲突 由于 Mercurial 没有给出任何建议 我什至不知道如何解决这个微不足道的文件冲突 冲突是微不足道的 但如果我不能解决这个问题
  • 如何使用waf构建共享库?

    我想使用构建一个共享库waf http code google com p waf 因为它看起来比 GNU 自动工具更容易 更简洁 到目前为止 我实际上有几个与我开始编写的 wscript 有关的问题 VERSION 0 0 1 APPNA

随机推荐

  • 提高 PHP GD 生成图像的质量

    我将开始使用 GD 库在 PHP 中构建地图生成器 我使用该库生成了一些图像 但它们的质量不佳 我只是想知道有什么方法可以提高图像质量 生成的图像是 我制作的代码是
  • 将阿拉伯语数据插入mysql数据库

    我尝试输入阿拉伯语文本并使用 php 将其插入到 mysql 数据库中 当打印该行时 阿拉伯语中的所有行如下所示 1 我将数据库设置为 字符集 utf8 UTF 8 Unicode 排序规则 utf8 general ci 以及数据库中的每
  • 使用复杂类型查询 Spark SQL DataFrame

    如何查询具有复杂类型 例如映射 数组 的 RDD 例如 当我编写这个测试代码时 case class Test name String map Map String String val map Map hello gt world hey
  • Zend Framework 2 - BjyAuthorize 始终拒绝访问

    我已经设置了bjyoungblood bjy authorize模块 但我目前正在得到一个403除在配置文件中配置的 URL 之外 每个 URL 都会出现 访问被拒绝 错误home route My module byjauthorize
  • 在烧瓶应用程序中保留全局状态[重复]

    这个问题在这里已经有答案了 我正在尝试将缓存字典保存在我的flask应用 据我了解 应用上下文 特别是烧瓶 g 对象应该用于此目的 Setup import flask as f app f Flask name 现在如果我这样做 with
  • 如何引用同一 appsettings.json 文件中的另一个值?

    我需要在 appsettings json 中的两个位置使用数据库连接字符串 是否可以在 json 文件中引入公共变量或 json path 相关引用以避免潜在的问题 如果能在不接触 C 代码的情况下拥有它 那就太棒了 Connection
  • 使用 sed 编辑 crontab

    我正在编写一个 sed 命令 该命令应取消注释 crontab 中的条目 有一个更好的方法吗 我想到的第一个选项是 sed Example crontab l 5 3 bash test sh sed 命令应取消注释该条目 这就是我现在所拥
  • 使用 JavaScript 更改 HTML 名称属性

    按下一个div 我把它做成了button与其他代码 我想要以下代码 div 1 br div 更改名称name w1 0 to name w1 1 我正在使用以下 JavaScript function weekclick id docum
  • 模数运算符运行第一项,然后每第三项运行

    所以我需要它在第一个循环上运行 然后在每个第三个循环上运行 if k 3 k 1 echo div class modcontainer 对我来说似乎很简单 但我不了解模数 模数返回余数 而不是布尔值 这段代码将解析为true for 1
  • 如何根据 R 中的列值范围拆分数据框?

    我有一个这样的数据集 Users Age 1 2 2 7 3 10 4 3 5 8 6 20 如何将此数据集拆分为 3 个数据集 其中第一个数据集包含年龄在 0 5 岁之间的所有用户 第二个数据集包含 6 10 岁 第三个数据集包含 11
  • 在 iOS4 中 UIWebView 播放视频损坏?

    我有一个从 SDK 2 0 版开始运行的应用程序 我在其中创建并添加 UIWebView 然后加载 mov 的 URL 来播放电影 从 4 0 beta 的早期版本到 4 0 GM 此功能已停止工作 当我现在加载电影时 出现以下错误 插件处
  • 使用 savemat 保存和加载 Python dict 会导致错误

    这是我收到的错误的一个最小示例 如果我正确理解了文档 这应该可以工作 但似乎我没有 a a test1 1 a test2 2 a test3 3 import scipy io as io io savemat temp a a b io
  • Android Instant Apps - 无法“运行未经验证的软件、运行任意本机代码”。仅即时应用程序运行时

    Android Instant Apps 文档中指出受限功能部分它不能 运行未经验证的软件 运行任意本机代码或动态加载除免安装应用运行时提供的代码之外的代码 我不完全理解上述声明 但在我看来 它可能不接受任何第三方软件或除中给出的库之外的任
  • Bash:Git 子模块 foreach?

    I have sup别名为submodule foreach git co master git up co up是别名checkout pull rebase 分别 如何添加条件 以便如果子模块名称是Libraries JSONKit 它
  • 设置 Scrapy 代理中间件在每个请求上轮换

    这个问题必然有两种形式 因为我不知道更好的解决途径 我正在爬行的网站经常将我踢到重定向的 用户被阻止 页面 但频率 按请求 时间 似乎是随机的 并且他们似乎有一个黑名单阻止了我正在使用的许多 开放 代理列表通过代理网格 所以 当 Scrap
  • Node.js - Express.js JWT 始终在浏览器响应中返回无效令牌错误

    我正在使用node js和express js快递 jwt模块 并且我设置了一个简单的 HTTP 服务器来测试所有内容 这是涉及的节点代码 app set port process env PORT 3000 app use express
  • Kubernetes - 没有选择器的服务

    我正在为没有选择器的 Kubernetes 服务而苦苦挣扎 该集群通过 kops 安装在 AWS 上 我有一个包含 3 个 nginx pod 的部署 暴露端口 80 apiVersion apps v1 kind Deployment m
  • 会话的跨子域 cookie 处理?

    是否可以设置一个有效的身份验证 cookie sub1 domain com sub2 domain com 或者每个子域总是需要它自己的 cookie 如果指定要附加到域的 cookie 则可以跨子域使用 cookie domain co
  • 拳击和加宽

    这两者有什么区别呢 我知道拳击正在将原始值转换为引用 什么是扩大 另外 首先应该进行拳击还是应该进行加宽的顺序应该是什么 扩大对拳击和 var args 的胜利 拳击战胜了 var args 引用变量的扩宽取决于继承 因此 Integer
  • 如何使用 Mercurial 子存​​储库来共享组件和依赖项?

    我们使用 C 开发 NET 企业软件 我们正在寻求改进我们的版本控制系统 我以前使用过mercurial 并且一直在我们公司尝试使用它 然而 由于我们开发企业产品 我们非常关注可重用的组件或模块 我一直在尝试使用 Mercurial 的子存