Git:忽略公共存储库的文件,但不是私有的

时间:2012-01-04 04:23:26

标签: git version-control

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

(我了解Heroku的Config变量,这是一个很好的临时解决方案,但如果我需要切换主机,那就不好玩了。)

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

我尝试过各种各样的事情:

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

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

的.git /配置

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

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

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

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

8 个答案:

答案 0 :(得分:16)

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

子模块只是对存储在存储库中的另一个存储库的引用,以及检出存储库的特定提交正在跟踪。你可以说使用

更新
git submodule update --recursive sensitive-files

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

ln -sf sensitive-files/shadow passwd

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

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

更新:

抱歉,如果你还在处理这个问题我错过了通知。

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

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

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

答案 1 :(得分:7)

您可以在本地仓库中创建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 hook的Web变体,所以除非你是自己的repo主机,否则这种方法只能在本地执行。

答案 2 :(得分:2)

执行此操作的一种方法是将您的私人文件放在子模块中,并从您的公共存储库中引用该模块。 (或者,您可以将 public 文件放在子模块中,并从私人仓库中引用该repo。)

答案 3 :(得分:2)

以下是其他一些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."

答案 4 :(得分:2)

一个名叫David Albert的人写了a tool called Junk来解决这个问题。它允许来自单独“垃圾抽屉”存储库的文件与主存储库中的文件一起存在。

私有文件将从公共文件中单独提交,但它可能会起作用。

答案 5 :(得分:1)

创建2个分支。具有私有文件的一个分支将不会被推送到公共存储库。合并后,使用git checkout HEAD^ -- files that should not have been mergedrm other filesgit add -Agit commit --amend -C HEAD还原相关文件。我不确定有问题的文件有什么不同但是你明白了。为此制作一个小脚本,你很高兴。您甚至可以提交您在根目录下提交的敏感文件列表,脚本可以执行此操作。

答案 6 :(得分:0)

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

您可以拥有私有文件的第二个存储库,以及在部署时将更改复制到生产系统上正确位置的小脚本。

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

答案 7 :(得分:0)

看起来你可以使用mine

基本上,它告诉git避免遵循约定<file or directory>_mine_之后的内容,并且工具本身会为您提供snapshotcleanrestore函数,而不是完整的成熟的版本,但对于个人的东西,它很好地完成了。

整件事pretty concise