【问题标题】:How to version control files which shouldn't be pushed to a remote repository?如何对不应该推送到远程存储库的文件进行版本控制?
【发布时间】:2019-12-15 11:26:27
【问题描述】:

我正在与我的团队合作开发 Rails API 存储库,我们有一个 .env 文件,其中包含我们的环境变量。该文件包含在 .gitignore 文件中,因为环境变量包含我们不想检查版本控制或推送到 Github 的敏感令牌。

当我遇到与这些环境变量相关的错误时,这会产生问题。团队中的每个人似乎都有一组略有不同(或有时大不相同)的环境变量,他们用于本地设置(长话短说,我知道这是根本原因,需要改变,但作为一名新顾问,我限制了暂时可以更改)。

我想到的一个短期解决方法是拥有一个没有远程的本地 git 存储库,仅用于 .env 文件(以及任何不应推送到远程主机的类似文件)。这至少让我能够回滚,检查差异以查看确切的更改内容,并阅读提交消息以提醒有关更改原因的提示。但由于已经有一个 git 存储库跟踪对大多数代码库的更改,我不确定是否可以创建第二个存储库。

我阅读了this post,但在涉及 .gitignore 文件时似乎遇到了同样的问题。

我也考虑过使用 git 子模块,但这些子模块是否仅用于子目录,或者如果两个 .git/ 文件夹是同一目录中的兄弟,它们是否也可以工作?

【问题讨论】:

    标签: git


    【解决方案1】:

    Git 不要求存储库或其工作树位于任何特定位置。您可以将其指向您正在使用的特定工作树和/或存储库,它会使用它们而不是查找它们。

    所以不要改动你的主存储库,并为你的.env 文件维护一个边带存储库。

    git init ~/orts.git
    git config --global alias.orts '!git --work-tree "$PWD" --git-dir ~/orts.git'
    

    然后你可以做例如

    git orts add .env
    

    【讨论】:

    • 我最终做了一个不太复杂的版本。我想要版本的.env 的repo 与同一客户端的其他几个项目位于同一父目录中。我实际上想将他们所有的 .env 文件版本化在一起,所以我在该父目录中运行 git init 并将该父目录的 .gitignore 文件中的 .env 文件列入白名单。顺便说一句,出于好奇-“orts”在这里指的是什么?您是否用它来表示“一顿饭中的食物残渣或剩余部分”,即类似于“面包屑”?如果是这样,我期待在我的机器上向人们展示“git crumbs”命令哈哈。
    • 差不多就是这样,主要事件的剩余部分。我不会称您提出的设置不那么复杂,在我看来,您似乎已经很好地掌握了它的工作原理。如果您要像这样在多个工作树之间共享一个存储库,我会考虑使其裸露并明确管理索引,git 命令不采用索引文件参数,其覆盖是环境- 只是,我冒险这样做只是因为没有人足够关心它提供补丁。
    【解决方案2】:

    无可争议(我认为)和无可争议(我认为):

    • 如果您需要对某些文件集进行版本控制,则必须将它们放入版本控制系统中。
    • 如果 VCS 是分布式的(与 Git 一样)并将所有文件发送到其他地方(与 Git 一样 — 它们在提交中并且只能共享整个提交),那么这不适合您的用例。李>
    • 但您想对其余文件使用 Git。

    结论:您至少需要两个 VCS 和/或存储库。

    第二个 VCS 也可以是 Git,只要您确保分发(至少以公开方式)第二个存储库。

    子模块可以工作。子模块只不过是对其他 Git 存储库的引用:本质上是一个 URL 和一个特定的提交哈希 ID。但是,每个 Git 存储库都控制自己的工作树。如果文件必须混合在一起(“存在于同一个文件夹中”),并且您仍然想使用子模块,那么您有几个选择:

    • 处理它(见下文);
    • 不要将 Git 工作树用作您的实际工作区;
    • 如果您的系统支持符号链接,并且涉及的文件不多,则让一个存储库包含指向实际位于另一存储库工作树中的文件的符号链接;或
    • 不使用任何符号链接,因此您明显统一的工作树只是指向所需子目录中文件的符号链接树。

    请注意,如果您确实选择使用子模块,您可能希望将其构建为一个单一的超级项目,该超级项目除了持有两个持有感兴趣的提交的子模块(可能还有森林符号链接,如果你在这里使用最后一种方法)。这使得两个子模块彼此完全独立,因为子模块不知道它的超级项目。只有 第三个​​ 存储库(即超级项目)会知道还有其他两个 Git 存储库涉及,并且超级项目将子模块安排在相对符号链接的位置(如果您使用那些)工作。

    如果这太过分了,只需选择两个独立的 Git 存储库之一作为超级项目。另一个 Git 存储库将被克隆为超级项目的子目录。

    关于“处理它”

    假设存储库 A 的提交仅包含公共文件,存储库 B 的提交仅包含私有文件。当您同时克隆AB 时,您会得到两个不同的工作树。其中一个最多可以是path/to/files,但您希望A B 中的文件都出现在path/to/files 中。如果 A 的工作树被命名为 path/to/files:

    cd path/to; git clone url-of-A files
    

    那么B的工作树肯定不是path/to/files,从B签出的文件不会最初出现在path/to/files中。例如,假设 B 根本不是子模块,而你现在——虽然还在 path/to 中——运行:

    git clone url-of-B sensitive-files
    

    您现在拥有files/*(将 Git-repo 克隆到 files/.git)持有从 repo A 提取的文件,sensitive-files/* 持有从 repo B 提取的文件。您现在可以手动或使用脚本,复制或符号链接sensitive-files/* 中管理的文件,以便可以通过具有files/* 形式的名称访问它们。

    files/* 中出现的副本或符号链接可以在 files/.gitignore 中列出,这样它们就不会被添加到 repo A 的提交中。或者,如果您正在使用符号链接,请注意A/sensitive-file-1 中的内容实际上只是路径名 ../sensitive-files/sensitive-file-1。将 symlink 提交到 repo A 可能是可以的,即使 repo A 可以从任何地方访问,因为获得它的副本的人只知道 A 中的程序可能读取和/或写入到一个名为sensitive-file-1 的文件。该文件的实际内容不在path/to/files 中,而是在path/to/sensitive-files 中,因此它们根本不会出现在repo A 中。

    【讨论】:

    • 嗨@torek,你能澄清if the files must be intermingled的意思吗?我确实需要文件存在于同一个文件夹中,但我希望 git 存储库将是互斥的,并且每个文件应该属于一个存储库或另一个(从不属于两者)。
    • “混合”是指“来自存储库 A 的文件可以在 path/to/files 中找到,来自存储库 B 的文件也可以在 path/to/files 中找到”。这意味着path/to/files 不得要么 A或B的工作树,,您必须从将两个工作树(A 或 B)中的一个放入另一个工作树(四个要点中的第二个——可能是手动复制的问题,或执行此操作的脚本)或使用第三个或第四个要点方法。
    【解决方案3】:

    我们有一个 .env 文件......我们不想检查版本控制

    所以...您有一个想要保持同步的文件,但您不想对其使用版本控制。所以,用别的东西?共享文件系统或小型网站。哎呀,如果没有路由器,那么简单的 FTP 就可以解决问题。

    您可以加密文件。

    环境变量包括敏感标记

    这是我要重新考虑的部分,因为它很奇怪。真正敏感的数据永远不会在环境中。

    【讨论】:

    • 我确实想使用版本控制来管理这个文件,我只是不想将 git 分支推送到远程服务器。至于将敏感数据存储在环境变量中,我的印象是这是一种常见的做法。这就是代币在 Heroku 以及其他平台上的存储方式。看到这篇文章-stackoverflow.com/a/11300680/2143275
    • 澄清一下——我想在本地使用第二个 git 存储库,以便我个人更容易管理 .env 文件。同时,更大的团队将继续使用原始 git 存储库管理项目的其余部分。希望这是有道理的。
    猜你喜欢
    • 2011-01-21
    • 2019-09-18
    • 2015-01-22
    • 1970-01-01
    • 2020-11-27
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    相关资源
    最近更新 更多