跟踪文件,但将其从git包中排除 [英] Track files but exclude them from a git bundle

查看:215
本文介绍了跟踪文件,但将其从git包中排除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



是否有人有工作流推荐或git命令,除了使用.gitignore(因为这些文件需要跟踪,所以我可以在紧急情况下回滚),这将帮助我完成这项工作? 解决方案



基本上,在Git中记录一个文件当且仅当它在索引中。索引(通常是最初)从某个提交填充,因此它是一些先前的提交,用于确定是否要跟踪文件。假设存在一组提交 T U ,它们是相似的,除了有一些文件不在提交 U 中提交 Ť。然后:

  git checkout任何-T-sub-i-commit 

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

  git checkout any -U-sub-j-commit 

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



对于像合并这样的操作,更一般的方式也是如此:当您使用从集合 T 提交,你使用那些有文件的工作;当你处理来自set U 的提交时,你可以使用那些缺少文件的提交。如果您将任何 T i 提交与任何 U j 提交合并,对任何此类文件的影响 - 添加,删除或冲突 - 取决于合并基础提交是否已设置 T 或设置 U ,以及commit T中对这些文件的特定更改 b

当然,当文件移入或移出索引时,Git也会将它们同时复制到工作树中或从工作树中删除它们(关于不删除未保存但非常珍贵的数据的通常注意事项)。所以这意味着工作树文件将会​​消失并且重新出现,这取决于你是否签出了一个提交或者提交一个提交。



同时,让我们看看一个包是什么,至少从抽象的角度来看。 bundle的本质是它至少包含所有 git fetch 或 git push 会在 git fetch git push 通讯过程之后发送,以便将此数据最小化。 (它可以包含额外的数据,这些数据将被简单地忽略)。这些最小数据由所有必须复制的对象组成 - 注释标记,提交,树和blob - 以及引用名称和值。



要从捆绑包中排除一些文件集,则需要仅捆绑 U 提交,而不是任何 T 提交。这很好:如果你有所有的分支都是重复的,并且按照分支名称来区分 T 提交和 U 提交,你可以非常容易地实现这一点。但结果是,每当你创建新的 T 提交时,你都必须进行相应的 U 提交,反之亦然。实际上,您的工作量增加了一倍。



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

这仍然不是微不足道的 - 尤其是,你可能必须编写一个包装器,并以正确的方式教导用户运行你的特定系统。但是这与你可能达到的微不足道的接近。






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

I have a somewhat complex ansible workflow. I have two airgapped networks. I develop playbooks on both networks, so I have two somewhat independent ansible repositories managed by git. At the same time, most of the playbooks can be used in both places. To complicate matters, this is a one way transfer. I can transfer from network A to B, but not from B to A.

I have template files with information relevant to one network but not relevant on the other. I've designed it so that filenames should be the same (as well as variable names in Jinja2 templates). I want to be able to create a git bundle that excludes the files, so that when I pull from the bundle on the other network's repository, the files don't get overwritten. Because including the wrong information in the template files could conceivably break the entire environment, I need to track the Jinja2 template/variable files in Git.

Does anyone have a workflow recommendation, or a git command besides using .gitignore (because the files need to be tracked so I can roll back in emergencies) that will help me accomplish this?

解决方案

There's no completely trivial way to do this.

Fundamentally, a file is tracked in Git if and only if it is in the index. The index is (normally, initially) populated from some commit, so that it is some previous commit that determines if a file is to be tracked. Assume there exist sets of commits T and U that are similar except that there are some files not in commits U that are in commits T. Then:

git checkout any-T-sub-i-commit

results in the file(s) being in the index (and hence tracked), while:

git checkout any-U-sub-j-commit

results in the file(s) being not-in the index (and hence untracked).

The same holds in a more general fashion for operations like merging: when you work with commits from set T, you work with the ones that have the files; when you work with commits from set U, you work with the ones that lack the files. If you merge any Ti commit with any Uj commit, the effect on any such file—whether it's added, removed, or conflicted—depends on whether the merge-base commit is in set T or set U, and the specific changes to those files within commit Ti with respect to the merge base commit.

Of course, as files move into or out of the index, Git also copies them into, or removes them from, the work-tree at the same time (with the usual caution about not removing unsaved-but-precious data). So this means that the work-tree file will vanish and reappear depending on whether you check out a T commit or a U commit.

Meanwhile, let's look at what a bundle is, at least in an abstract sense. The essence of a bundle is that it contains at least all the data that git fetch or git push would send across the wire, after the git fetch or git push communication process that serves to minimize this data. (It can contain extra data, which will simply be ignored.) This minimal data consists of all of the objects that must be copied—annotated tags, commits, trees, and blobs—plus the reference names and their values.

To exclude some set of files from the bundle, then, you need to bundle exclusively the U commits, and not any of the T commits. That's fine as far as it goes: if you have all branches duplicated, and distinguish between T commits and U commits by branch names, you can achieve this pretty easily. But the consequence is that every time you make a new T commit you must make a corresponding U commit, and vice versa. You have, in effect, doubled your workload.

The standard recommendation that applies to configuration files in general applies here as well: Do not commit any configuration, ever. Commit only sample or default or template configurations. Use some kind of wrapper to convert these sample configurations to real configurations. (The wrapper can also be committed, of course, if it's something you write yourself, such as a shell script or Python program or whatever.) You may now maintain, and version-control, these sample / default configurations. Cloning the repository obtains the samples, and updating from the clone—git fetch followed by a merge or rebase—updates the samples, but does not touch the actual configuration. Depending on how smart the wrapper is and what's available in your output format,1 it can even auto-detect that the sample/default input has changed, and warn or fail any runs that use the prescribed tool (i.e., the wrapper itself) until the real configuration is updated to match any required changes coming from the sample/default/template configuration.

This is still not trivial—in particular, you may have to write a wrapper, and educate users on the correct way to run your particular system. But it's as close to trivial as you are likely to achieve.


1In this particular case, your output is most likely the YAML files for ansible. This means you can hide all kinds of useful sample/default-config information in comments, for instance.

这篇关于跟踪文件,但将其从git包中排除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆