【问题标题】:Git: Ignore files for public repository, but not for privateGit:忽略公共存储库的文件,但不考虑私有存储库
【发布时间】:2012-02-02 01:35:26
【问题描述】:

我正在通过 git 在 Heroku(目前)上部署一个 Rails 应用程序,并且还希望有一个公共版本供人们查看。有些文件是敏感的,应该只提交和推送到“heroku”分支,而不是“公共”分支。 最好的方法是什么?

(我确实知道 Heroku 的 Config 变量,它作为临时解决方案非常棒,但在我需要切换主机时并不好玩。)

这两个分支不需要一直同步 - 我可以定期将“master”分支合并到“public”分支并分别推送到 github。

我尝试了各种方法:

  • 分离 .gitignore 文件和“我们的”合并策略 - 起初这不起作用,在搞砸了一段时间后,我觉得它变得太复杂了,所以我可以实现一个看似简单的任务

  • 使用自定义 exclude 文件,并将以下内容添加到 .git/config... 这根本行不通:

.git/config

[branch "public"]
  excludesfile = +info/exclude_from_public

让私有和公共存储库共享相同代码但忽略公共存储库中的敏感文件的最佳方法是什么?

您可以假设没有代码被提交或推送,即这是一个新初始化的存储库。

(以前曾以各种形式提出过这个问题,但没有一个答案是直截了当的,或者答案似乎真的很老套。我只是在这里以一种非常简单的方式提出这个问题,并希望收到一个非常简单的回复。)

【问题讨论】:

  • 可以删除公共分支的文件吗?
  • 是的,但是这样我会与.gitignore 发生合并冲突,当我运行git merge master 时,文件将被添加回public 分支
  • 如果你有信心使用多个版本控制系统,你可以使用 darcs/mercurial/svn/bzr/whatever 作为私有分支,并选择性地推送到 git。
  • 您需要隐藏哪些具体文件?也许我们可以建议一种更简单的方法来解决这个问题,例如使用 Heroku 配置变量。
  • @Emily initializers/secret_token.rb,以及一些包含一些加密信息(管理员登录和 s3 凭据)的 YAML 文件

标签: git version-control


【解决方案1】:

我将支持子模块的答案,但尝试提供一些说明。首先,git 不处理文件,而是处理提交。无法过滤分支中的文件或路径,因为分支实际上是指向提交的指针。当您排除或忽略时,您只是在阻止文件被添加到您的存储库中。甚至没有任何“敏感文件”文件在存储库中,只是在您的工作目录中。

子模块只是对存储在您的存储库中的另一个存储库的引用,并且该签出存储库正在跟踪的特定提交。你可以说更新使用

git submodule update --recursive sensitive-files

为了简化事情,您可以在指向子模块路径的适当位置提交符号链接。

ln -sf sensitive-files/shadow passwd

然后像添加任何其他文件一样添加符号链接..

请记住,子模块只是一个签出的 git 存储库,您可以轻松地限制对该实际存储库的访问并将主要的存储库公开。

更新:

抱歉,如果您仍在处理此问题,我错过了通知。

您的私有存储库中可以有多个符号链接,这些符号链接引用在子目录中检出的私有存储库(子模块)。Rails 实例使用的每个数据库或任何内容都可以是指向该私有子目录的符号链接。

此外,您不需要远程指向私有存储库,只需 .gitmodules 文件中的一个条目,该条目由 git 子模块 自动维护。您仍然需要保护私有存储库,以便只有您的 Heroku 实例可以访问它。为此,如果可以或使用其他一些私有 git 托管解决方案,我建议在服务器上安装 gitosis。将与您的实例私钥匹配的公共 ssh 密钥添加到允许的用户列表中。 (我不熟悉如何在 Heroku 中执行此操作。)

当您将更改推送到 heroku 时,它应该递归下载存储库中提到的所有子模块。

【讨论】:

  • 感谢您的澄清。我可能会接受您的回答,但是我想进一步澄清一下。为了做到这一点,我需要一个私人 git 存储库,对吗?此外,敏感信息位于我的 Rails 目录结构中的各个位置......我可以将“私人仓库”签出到适当的位置,还是私人仓库必须基本上只有一种 Rails 文件的数据库文件可以参考吗?最后,我在 Heroku 上的 repo 是否会远程引用“私人 repo”,或者我可以将其全部检查到 Heroku 中吗?谢谢!
【解决方案2】:

你可以在你的本地仓库中创建一个pre-commit hook,在这里你可以编写一个脚本来检查当前签出的分支并删除有问题的文件(如果它们在处理提交之前存在)。这样可以避免文件被记录在错误分支的 Git 历史记录中。

#!/bin/bash
current_branch="$(git branch | sed -e 's/^*//')"
if [ $current_branch != "heroku" ]; then 
    // Delete sensitive files before commit
    rm -f dir1/dir2/exclude_from_public
    rm -f dir1/dir2/exclude_from_public_also
fi
exit 0

或者,脚本可以只检查文件并返回退出代码“1”,通知您提交无法继续,因为它包含敏感文件。

需要注意的是,您需要将此脚本交给在“特权”heroku 分支上工作的任何人,并始终将其包含在您自己的本地存储库中。

理想情况下,您也应该在服务器端完成这项检查;但不幸的是 GitHub 只提供了 post-receive 钩子的 Web 变体,所以除非你提供你自己的 repo 托管,否则这种方法只能在本地执行。

【讨论】:

    【解决方案3】:

    这样做的一种方法是将您的私有文件放在一个子模块中,并从您的公共存储库中引用该模块。 (或者,您可以将 public 文件放在子模块中,并从您的私有仓库中引用该仓库。)

    【讨论】:

    • 我知道这是如何工作的,但是忽略两个文件似乎是一种过于复杂的方法。我会等着看别人怎么说。感谢您的回复。
    • 如果您的文件与您要保留的常规文件位于同一目录中,则此策略不起作用。子模块用于缩减其他项目、库等——而不是用于处理一个存储库中的一小部分文件。
    【解决方案4】:

    这里有一些其他 StackOverflow 问题和答案,与“如何在忽略某些文件的情况下进行合并”有关:

    我能想到的最简单的方法是使用alias'ed 合并,它将在执行合并提交之前删除私有文件。如果您愿意接受非快进合并,这将起作用。这是alias

    git config alias.merge-master-exclude-private '!git merge --no-commit --no-ff master && (git diff --name-only HEAD..master | grep -f private_files | while read f; do git reset HEAD -- "$f"; rm -f "$f"; done; git commit -m "Merge master, excluding private files.")'
    

    然后编辑private_files文件并添加私有文件模式;例如secret_file.*$。您可以将别名中的private_files 替换为"$(git rev-parse --show-toplevel)"/private_files 以从顶级目录中读取private_files

    使用git merge-master-exclude-private 进行合并。这将在不提交的情况下执行非快进合并,在private_files 文件中查找与模式匹配的文件,reset 找到的任何私有文件的索引,删除工作目录中的私有文件,然后提交。这应该处理名称中包含空格的文件。

    如果您不想进行提交,让您有机会编辑提交消息,请从别名中删除 -m "Merge master, excluding private files."

    【讨论】:

      【解决方案5】:

      一个名叫大卫阿尔伯特的人写了a tool called Junk 几乎完全解决了这个问题。它允许来自单独的“垃圾抽屉”存储库的文件与主存储库中的文件并存。

      私有文件将与公共文件分开提交,但它可能会完成这项工作。

      【讨论】:

        【解决方案6】:

        创建 2 个分支。拥有私有文件的分支不会被推送到公共仓库。合并后,使用git checkout HEAD^ -- files that should not have been mergedrm other filesgit add -Agit commit --amend -C HEAD 恢复有问题的文件。我不确定有问题的文件有什么区别,但你明白了。为此制作一个小脚本,您就可以开始了。您甚至可以提交您在根目录下提交的敏感文件列表,脚本可以根据该列表采取行动。

        【讨论】:

        • 这个方法我不太懂……你能再解释一下吗?这会将敏感文件完全排除在公共回购的提交历史之外吗?
        • 只是不要推送私有分支
        【解决方案7】:

        我知道这回避了这个问题,但我只需要两个 git 存储库。然后,您可以将它们永久添加到公共存储库的忽略列表中。

        在进行部署时,您可以为私有文件创建第二个存储库,并使用一个小脚本将更改复制到生产系统上的正确位置。

        这降低了当您去度假并且新实习生更新公共回购时,您的私人信息会意外泄露的风险。 ;-)

        【讨论】:

          【解决方案8】:

          看起来你可以使用mine

          基本上,它告诉 git 避开遵循约定 <file or directory>_mine_ 的东西,并且工具本身为您提供了 snapshotcleanrestore 功能,不是完整的版本控制,而是用于个人内容它做得很好。

          整个事情都是pretty concise

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-12-19
            • 2019-08-30
            • 2013-03-09
            • 2011-12-27
            • 2017-08-18
            • 1970-01-01
            • 1970-01-01
            • 2019-11-08
            相关资源
            最近更新 更多