【问题标题】:Track files but exclude them from a git bundle跟踪文件但从 git 包中排除它们
【发布时间】:2018-02-18 10:18:54
【问题描述】:

我有一个有点复杂的 ansible 工作流程。我有两个气隙网络。我在两个网络上都开发了剧本,所以我有两个由 git 管理的有点独立的 ansible 存储库。同时,大部分剧本都可以在这两个地方使用。更复杂的是,这是一种单向转移。我可以从网络 A 转移到 B,但不能从 B 转移到 A。

我有模板文件,其中包含与一个网络相关但与另一个网络无关的信息。我已经设计了它,以便文件名应该相同(以及 Jinja2 模板中的变量名)。我希望能够创建一个排除文件的 git 包,这样当我从另一个网络存储库上的包中提取时,文件不会被覆盖。因为在模板文件中包含错误信息可能会破坏整个环境,所以我需要在 Git 中跟踪 Jinja2 模板/变量文件。

除了使用 .gitignore(因为需要跟踪文件以便我可以在紧急情况下回滚)之外,是否有人有工作流建议或 git 命令可以帮助我完成此任务?

【问题讨论】:

  • 好的,作为后续,由于我无法跟踪此存储库结构中的配置数据,有没有办法可以使用 .gitignore 文件来排除特定目录(或多个目录)主存储库,然后一些如何创建文件树中存在的第二个 git 存储库来跟踪实际配置数据?我不抱太大希望,因为这是一个非常混乱和复杂的情况,我在过去 20 年中学到的关于系统管理的一切都尖叫着不要这样做......但如果我必须这样做,我可以吗?
  • 你可以使用 Git 子模块来做到这一点。不过,我不喜欢子模块;如果可能的话,我会避开它们。子模块本质上是一个单独的 Git 存储库,在父(“超级项目”)存储库中,您记录应该从另一个存储库使用哪个特定的 commit。这只是将子模块的原始哈希 ID 保存在 Git 称为“超级项目”的纯文本文件中的一种更加自动化的形式。因此,您可以(通过 bundle 或其他方式)传输超级项目数据,而无需打扰其他 Git 存储库。
  • 我当然同意你对使用这样的东西的犹豫。我只想制定某种备份计划,以防我找不到其他合理的解决方案来跟踪更改。我确实喜欢配置脚本的想法。我正在考虑在 repo 中有一个单独的分支来跟踪这些事情,然后我可以确保脚本仅在文件系统树中作为积极行动的结果。安全性好!非常感谢您的建议和帮助!

标签: git ansible git-bundle


【解决方案1】:

没有完全简单的方法可以做到这一点。

从根本上说,当且仅当文件在索引中时,文件才会在 Git 中被跟踪。该索引(通常,最初)是从某个提交中填充的,因此它是某个先前的提交来确定是否要跟踪文件。假设存在类似的提交集 TU,除了提交 U 中的一些文件不在提交 中T。那么:

git checkout any-T-sub-i-commit

导致文件在索引中(并因此被跟踪),而:

git checkout any-U-sub-j-commit

导致文件不在索引中(因此未被跟踪)。

对于像合并这样的操作来说,这同样适用于更一般的方式:当你处理来自集合 T 的提交时,你会处理那些拥有文件的提交;当您处理来自集合 U 的提交时,您使用的是缺少文件的提交。如果您将任何 Ti 提交与任何 Uj 提交合并,则对任何此类文件的影响——无论它是添加、删除或冲突——取决于合并基础提交是在集合 T 还是集合 U 中,以及在提交 T 中对这些文件的具体更改i 关于合并基础提交。

当然,当文件移入或移出索引时,Git 也会同时将它们复制到工作树中或从工作树中删除(通常注意不要删除未保存但宝贵的数据) .因此,这意味着工作树文件将消失并重新出现,具体取决于您是签出 T 提交还是 U 提交。

同时,让我们看看什么是捆绑包,至少在抽象意义上。捆绑包的本质是它至少包含git fetchgit pushgit fetchgit push 通信过程之后通过线路发送的所有数据,该通信过程用于最小化这个数据。 (它可以包含额外的数据,这些数据将被简单地忽略。)这个最小的数据包含所有必须复制的对象——带注释的标签、提交、树和 blob——加上引用名称和它们的值。

要从捆绑包中排除某些文件集,您需要专门捆绑 U 提交,而不是任何 T 提交。就目前而言,这很好:如果您复制了所有分支,并通过分支名称区分 T 提交和 U 提交,则可以很容易地实现这一点。但结果是每次你进行新的 T 提交时,你都必须进行相应的 U 提交,反之亦然。实际上,您的工作量增加了一倍。

适用于配置文件的标准建议通常也适用于此处:永远不要提交任何配置。仅提交 sampledefaulttemplate 配置。 使用某种包装器将这些示例配置转换为真实配置。 (当然,也可以提交包装器,如果它是您自己编写的东西,例如 shell 脚本或 Python 程序或其他任何东西。)您现在可以维护和版本控制这些示例/默认配置。克隆存储库获取示例,并从克隆更新(git fetch,然后进行合并或变基)更新示例,但不会触及实际配置。根据包装器的智能程度以及输出格式中可用的内容,1 它甚至可以自动检测示例/默认输入已更改,并警告或失败任何使用规定工具的运行 (即包装器本身),直到更新实际配置以匹配来自示例/默认/模板配置的任何所需更改。

这仍然不是微不足道的——特别是,您可能必须编写一个包装器,并教育用户以正确的方式运行您的特定系统。但它几乎是微不足道的。


1在这种特殊情况下,您的输出很可能是 ansible 的 YAML 文件。这意味着您可以在 cmets 中隐藏各种有用的示例/默认配置信息。

【讨论】:

  • 哇,我真的很感谢你把它放到如此正式的分析中!我的集合论有点生疏,但我明白你在解释什么。不幸的是,你也证实了我的怀疑和恐惧。我要么必须维护实际的配置值数据而不在同一个存储库中跟踪它,要么付出一些荒谬的努力将其从捆绑包中转移出去。
猜你喜欢
  • 2014-08-09
  • 2022-01-27
  • 2018-12-20
  • 2020-01-05
  • 2018-07-21
  • 1970-01-01
  • 2017-10-23
  • 2019-04-19
  • 1970-01-01
相关资源
最近更新 更多