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

发布于 2024-12-25 00:33:04 字数 788 浏览 1 评论 0原文

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

(我确实了解 Heroku 的配置变量,它作为临时解决方案很棒,但如果我需要切换主机。)

这两个分支不需要始终同步 - 我可以定期将“master”分支合并到“public”分支并将其单独推送到 github。

我尝试过各种方法:

  • 单独的.gitignore文件和“我们的”合并策略 - 这起初不起作用,在搞乱它一段时间后我发现它变得太了复杂只是为了实现一个看似简单的任务

  • ,并将以下内容添加到 .git/config...这根本不起作用:

.git/config

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

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

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

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

I'm deploying a Rails app on Heroku (for now) via git, and would also like to have a public version for people to look at. Some files are sensitive and should only be committed and pushed in the "heroku" branch, but not the "public" branch. What is the best way to go about this?

(I do know about Heroku's Config variables, which is great as a temporary solution, but not fun if and when I need to switch hosts.)

The two branches don't need to be synced at all times - I'm okay with periodically merging the "master" branch into the "public" branch and pushing it to github separately.

I have tried various things:

  • separate .gitignore files and an "ours" merge strategy - this didn't work at first, and after messing with it for a while I decided it was getting too complicated just so I could achieve a seemingly simple task

  • using a custom exclude file, and adding the following to .git/config... this simply did not work:

.git/config

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

What is the best way to have a private and public repository share the same code, but ignore sensitive files in the public repository?

You can assume that no code has been committed or pushed, i.e. this is a freshly initialized repository.

(This question has been asked before in various forms, but none of the answers were straight-forward or the answers seemed really hacky. I'm just here to ask this in a very simple manner, and hopefully receive a very simple response.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

终止放荡 2025-01-01 00:33:04

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

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

git submodule update --recursive sensitive-files

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

ln -sf sensitive-files/shadow passwd

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

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

更新:

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

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

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

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

I will second the submodule answer, but try to provide some clarification. First, git does not deal with files but with commits. There is no way to filter files or paths in a branch because a branch is really a pointer to a commit. When you exclude or ignore you are just keeping files from being added to your repository. none of the 'sensitive files' files are even in the repository, just in your working directory.

The submodule is just a reference to another repository stored in your repository, and a specific commit that that checked out repository is tracking. you can say update using

git submodule update --recursive sensitive-files

In order to simplify things, you can commit symlinks in the proper place pointing to the submodule path.

ln -sf sensitive-files/shadow passwd

Then add the symlink as you would any other file..

Remember the submodule is just a checked out git repository, you can easily restrict access to that actual repository and make the main one public.

Updated:

Sorry I missed the notification, if you are still working on this.

You can have multiple symlinks in your private repository referencing the private repository (submodule) which is checked out in a subdirectory.Each of the databases or whatever used by the Rails instance could be a symlink into that private subdirectory.

Also, you don' t need a remote pointing to the private repository, just an entry in the .gitmodules file which is maintained automatically by git submodule. You would still need to protect the private repository so that only your Heroku instance could access it. For that I would suggest installing gitosis on a server if you can or use some other private git hosting solution. Add the public ssh key matching your instances private key tothe list of allowed users. (I'm not familiar with how to do this in Heroku.)

When you push your changes to heroku it should recursive download all the submodules mentioned in the repository.

浮萍、无处依 2025-01-01 00:33:04

您可以在本地存储库中创建一个 预提交挂钩,在这里您可以编写一个脚本来检查当前检查分支并删除有问题的文件(如果它们在处理提交之前存在)。这可以避免文件被记录在错误分支的 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 变体,因此除非您这样做,否则您自己的存储库托管此方法只能在本地执行。

You could create a pre-commit hook in your local repo, in here you can write a script to check the currently checked out branch and delete the offending files if they are present before the commit is processed. This avoids the files ever being recorded in the Git history of the wrong branch.

#!/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

Alternatively, the script could just check for the files and return exit code "1", notifying you that the commit cannot proceed because it contains sensitive files.

The caveat is that you will need to hand this script to anyone who is working on the "privileged" heroku branch, and always have it included in your own local repo.

Ideally you would have this check done server-side as well; but unfortunately GitHub only offers a Web variant of the post-receive hook, so unless you do you're own repo hosting this approach can only be performed locally.

手心的温暖 2025-01-01 00:33:04

一种方法是将您的私有文件放入子模块中,并从您的公共存储库引用该模块。 (或者,您可以将您的公共文件放入子模块中,并从您的私人存储库中引用该存储库。)

One way to do this would be to put your private file(s) in a submodule, and refer to that module from your public repo. (Alternately, you could put your public files in a submodule, and refer to that repo from your private repo.)

甚是思念 2025-01-01 00:33:04

以下是一些其他 StackOverflow 问题和答案,主题是“如何在忽略某些文件的情况下进行合并”:

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

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 以从顶级目录。

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

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

Here are some other StackOverflow questions and answers along the line of "how do you do a merge while ignoring some files":

The simplest I can think of, is to use an alias'ed merge that will remove the private files before doing the merge commit. This would work if you're willing to live with non-fast-forward merges. Here's the 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.")'

Then edit the private_files file and add file patterns that are private; for example secret_file.*$. You could replace private_files in the alias with "$(git rev-parse --show-toplevel)"/private_files to read private_files from the top-level directory.

Use git merge-master-exclude-private to do the merge. This will execute a non-fast-forward merge without committing, find files matching patterns in the private_files file, reset the index of any private files found, remove private files in the working directory, then commit. This should handle files that have whitespace in their names.

If you don't want to do the commit, giving you a chance to edit the commit message, remove -m "Merge master, excluding private files." from the alias.

丶视觉 2025-01-01 00:33:04

一个名叫 David Albert 的人编写了一个名为 Junk 的工具来几乎完全解决这个问题。它允许来自单独的“垃圾抽屉”存储库的文件与主存储库中的文件并存。

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

A guy named David Albert wrote a tool called Junk to solve almost exactly this problem. It lets files from a separate “junk drawer” repository live alongside the ones in your main repository.

The private files will have separate commits from the public ones, but it might do the job.

旧瑾黎汐 2025-01-01 00:33:04

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

Create 2 branches. The one branch that has the private files will not be pushed to the public repo. After a merge, restore the files in question with git checkout HEAD^ -- files that should not have been merged, rm other files, git add -A and git commit --amend -C HEAD. I'm not sure what the difference in the files in question is but you get the idea. Make a small script for this and you're good to go. You could even commit a sensitive file list that you commit at the root and the script could act off of that.

失眠症患者 2025-01-01 00:33:04

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

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

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

I know this sidesteps the question, but I would simply have two git repositories. Then you can just add them permanently to the ignore list on the public repository.

You can have a second repository for the private files, and a small script to copy the changes to the correct location on the production system, when doing your deployment.

This reduces the risk that when you go on vacation and the new intern updates the public repo, your private information will accidentally get leaked. ;-)

静水深流 2025-01-01 00:33:04

看起来你可以使用 mine

基本上,它告诉 git 避开遵循约定<文件或目录>_mine_ 的内容,并且该工具本身为您提供快照干净 > 和 restore 功能,不是成熟的版本控制,但对于个人东西来说它可以很好地完成任务。

整个事情非常简洁

Looks like a you could use mine.

Basically, it tells git to steer clear of stuff following the convention <file or directory>_mine_ and the tool itself gives you a snapshot, clean, and restore function, not full-fledged versioning, but for personal stuff it does the trick nicely.

The whole thing's pretty concise.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文