如何使用 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 子存​​储库来共享组件和依赖项? 的相关文章

  • Libsourcey 缺少 -fPIC 编译错误

    我正在尝试运行 LibSourcey 以使用 Webrtc 流服务器 问题是我似乎无法让它发挥作用 我努力在我的 Ubuntu 16 04 上 cmake 该项目 cmake 文件中的正则表达式 但现在它已修复 我实际上遇到的问题是编译时的
  • 使用 Mercurial,我如何查看哪些更改尚未推送?

    我习惯了 git 你可以在其中运行 gitk 并得到如下内容 在这里您可以看到有一些更改需要推送到远程分支 或者 我可以使用git log decorate输出将是 b8c2926 refs heads next Update instru
  • Mercurial hook 的操作类似于“changegroup”,但仅在推送时?

    我们已经构建了一个变更集传播机制 但它依赖于捆绑和解除捆绑新变更集 如果我们要使用changegroup钩子 那么它会导致循环行为 因为钩子是运行的在拉 推或解绑期间 http mercurial selenic com wiki Hook
  • 如何将 Mercurial 存储库克隆到已存在的目录中?

    我有一个客户的 Django 项目 正在本地开发 使用 Mercurial 进行版本控制 我将本地存储库推送到我的个人远程服务器 我保存所有项目的地方 然后当我部署它时 在任何 Web 服务器上 我从我的个人服务器克隆该存储库 这在大多数服
  • 为dlib创建共享库

    按照说明使用 cmake 编译 dlib here http dlib net compile html 生成静态 dlib 库 cd examples mkdir build cd build cmake cmake build conf
  • Android:如何管理同一应用程序使用的多个库中的公共代码库

    NOTE 这个问题是基于我在以下讨论中收到的答案 Android 2个具有相同包的aar库 https stackoverflow com questions 57347039 android 2 aar libraries with th
  • 自动 npm install --legacy-peer-deps 用于单个依赖项

    假设我有一个package json像这样 name my app version 0 1 0 dependencies aws sdk client s3 3 21 0 testing library react 11 2 5 axios
  • 编译器 libstdc++ 版本与系统版本

    我试图了解 g 如何选择它链接的 libstdc 版本 以及当库的 系统 版本不同时它意味着什么 我正在使用 gcc g 4 1 2 根据ABI 指南 http gcc gnu org onlinedocs libstdc manual a
  • bitbucket、“hg 推送”和“hg 更新”

    如果我从本地 Mercurial 存储库开始 我认为它是 主要 存储库 请原谅我的 dvcs 领主 并打算使用 bitbucket 作为备份和问题跟踪工具 我可以在本地进行所有更改repo 并执行 hg Push 将更改发送回 bitbuc
  • 静态链接共享对象?或者损坏的文件?

    我有一个从专有来源获得的库 我正在尝试链接它 但出现以下错误 libxxx so 文件无法识别 文件格式无法识别 Collect2 ld 返回 1 退出状态 确实 ldd libxxx so statically linked 这究竟意味着
  • 有趣的是,当为 Mercurial 添加 .hgignore 时,该文件本身显示为“?”汞状态?

    正常吗 所以你只需要添加 hgignore到列表中忽略自身 是的 但你不想忽视 hgignore文件 当新人查看您的存储库时 您不希望他们获得您的忽略文件列表吗 相反 做hg add hgignore hg commit 底线 hgigno
  • 正在搜索 Mercurial 存储库 (TortoiseHG)?

    有什么方法可以输入特定的文件名 例如 xyz txt 并使用 TortoiseHG 在 Mercurial 存储库中搜索该文件的任何签入 如果没有 为什么不呢 这不就是版本控制的用途吗 在 Hg Repository Explorer 窗口
  • GCC 和 ld 找不到导出的符号...但它们在那里

    我有一个 C 库和一个 C 应用程序 尝试使用从该库导出的函数和类 该库构建良好 应用程序可以编译 但无法链接 我得到的错误遵循以下形式 app source file cpp text 0x2fdb 对 lib namespace Get
  • Mercurial 合并的默认主干版本?

    当我们将 Mercurial 功能发布存储库中的更改合并到主干存储库时 我们总是会与 Maven POM 文件 pom xml 和 Mercurial hgtags 文件发生冲突 我们总是想保留主干版本 我们永远不需要功能发布存储库版本 有
  • 忽略 Mercurial hook 中的某些 Mercurial 命令

    我有一个像这样的善变钩子 hooks pretxncommit myhook python path to file myhook 代码如下所示 def myhook ui repo kwargs do some stuff 但在我的例子中
  • 创建 C++ Redis 模块 - “不导出 RedisModule_OnLoad() 符号”

    我在加载 Redis 模块时遇到一些问题 我只是复制来自的示例https redis io topics modules intro https redis io topics modules intro 但我把它剥下来了 include
  • JavaScript 的依赖管理和构建工具

    我有许多跨多个项目共享的 JS snippets 和 文件 我必须将它们复制粘贴到每个项目的单个文件中 或者将它们作为 CDN 上的单独文件提供 两者都是坏主意 有没有类似 Maven for JavaScript 的依赖管理和构建工具 理
  • Fortran 中的共享库,最小示例不起作用

    我试图了解如何在 Linux 下的 Fortran 中动态创建和链接共享库 我有两个文件 第一个 liblol f90 看起来像这样 subroutine func print lol end subroutine func 我用它编译gf
  • 使用 Mercurial 自动构建的版本编号

    我们最近从 SVN 切换到 Mercurial 我们还设置了一个 CruiseControl NET 来运行自动构建 它从源代码控制中获取最新信息并构建应用程序 在用于自动构建的 CruiseControl NET 仪表板中 我们希望显示版
  • 获取Android库中的上下文

    我正在编写一个 Android 应用程序 它的一些功能封装在内部库中 但是 要使此功能发挥作用 库需要一个应用程序上下文的实例 为图书馆提供这种上下文的最佳方式是什么 我看到了一些选择 但没有一个有吸引力 Have my library c

随机推荐

  • 提高 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 的子存