问题 如何在Git中将提交的文件标记为只读?


我有一个文件,检入Git。该文件需要持有API密钥,但出于安全原因,我不希望将API密钥提交给Git。我解释了如何为每个开发人员生成API密钥而不是API密钥。

我不希望任何开发人员意外提交他们的API密钥并覆盖基本文件。

我有:

  • 将文件添加到 .gitignore 文件,但是,因为它已经提交,这不会做任何事情。
  • 跑完命令 git update-index --assume-unchanged myFile.js
  • 将该命令添加到说明文件以通知其他开发人员他们也应该运行此命令。

但是,我刚搬到我的笔记本电脑,忘了运行命令,并意外地将一把钥匙交给了回购。我正在寻找一种更加自动防故障的方法。本质上,我想将文件的初始版本提交给GitHub,然后禁止修改该文件。

这可能吗?

作为参考,该文件看起来像:

define(function () {
    //  The Simple API Access API key is used here.
    //  Please note that I've specifically omitted this key from GitHub for security. 
    //  Feel free to generate your own in order to use YouTube's API: https://code.google.com/apis/console/
    //  A valid key will look something like:
    //  Key for browser apps (with referers)
    //  API key: -------------------------------
    //  Referers: Any referer allowed
    //  Activated on:   Apr 6, 2014 2:46 PM
    //  Activated by:   ------------ – you
    //  NOTE: Please do not commit changes to this file once downloaded. CommandS:
    //  - Disable tracking: "git update-index --assume-unchanged src/js/background/key/youTubeAPI.js"
    //  - Enable tracking: "git update-index --no-assume-unchanged src/js/background/key/youTubeAPI.js"
    var key = 'API_KEY_MISSING';

    if (key === 'API_KEY_MISSING') {
        console.error('YouTube API key is not present.');
    }

    return key;
});

7604
2017-12-18 18:44


起源

如何检查有问题的文件的哈希值仍然使用一些 服务器端钩子 (pre-receive 要么 update)并拒绝任何修改该文件的推送? - jubobs
@Jubobs这看起来像是要走的路。你可以回答而不是评论,我会接受吗?谢谢。 (顺便说一下,这对GitHub不起作用,但它确实回答了我的问题。) - Sean Anderson


答案:


一种可能的方法是安装一些 服务器端钩子 (例如。 update) 那会

  1. 在推送的引用中检查所讨论的blob的散列是否保持不变,并且
  2. 拒绝任何包含引用的推送,其中有问题的blob的哈希值会发生变化。

当然,这样的服务器端钩子不会阻止贡献者创建包含不同版本文件的提交(本地,在他们的机器上)。然而,在看到他们的一些推动被拒绝后,他们肯定会吸取教训。 :p


5
2017-12-18 19:14





隐含主题行问题的答案(“我可以让git将特定文件检出为只读”)是“不,至少不是直接”,因为git每个文件只存储一个权限位:可执行文件,或者不是-executable。每个文件的所有其他位设置相同。

尽管如此,使用钩子有一些技巧。正如一些评论者建议的那样,您可以在服务器端钩子中测试某些内容以防止推送。您可以使用涂抹和清洁过滤器。你可以有一个 post-checkout hook将文件设置为只读。

任何和所有挂钩的缺点是必须为每个存储库设置它们,并且用户可以覆盖它们(服务器端挂钩除外,假设用户无法直接访问服务器)。1  这也是钩子的优点,虽然对于天真的用户来说,它可能比缺点更有缺点,因为git本身不会自动设置钩子。

post-checkout hook可能是设置文件权限最明显的地方,因为git的文档包括这一点:

此挂钩可用于...设置工作目录元数据属性。

方便的是,只要用户实际上在git工作树中,钩子似乎总是在顶级目录中运行,而不管用户在哪里。2  所以这个非常简单的钩子足以将一个文件更改为只读:

#! /bin/sh
# post-checkout hook to make one file read-only
chmod -w path/to/file

(在任何系统上 chmod 无论如何,记得将钩子设置为可执行文件)。

用户必须将此挂钩放入他/她的存储库中 .git/hooks/post-checkout (尽管您可以将文件本身提交到存储库中,然后让用户将其复制或链接到位,可能通过辅助设置脚本)。


1因此,如果您愿意,可以使用服务器端挂钩 严格执行 政策(一般情况下都是如此)。

2也就是说,以下内容击败了钩子:

$ pwd
/home/user/dir/example
$ ls -l .git/hooks/post-checkout
-rwxr-xr-x  1 user  group  27 Dec 18 11:10 .git/hooks/post-checkout
$ cd /tmp
$ GIT_DIR=/home/user/dir/example/.git git checkout master

这里,当前的工作目录就是 /tmp,并没有办法让钩子弄清楚它应该是什么(你可以阅读 $GIT_DIR,但这不一定有用 .git 目录不需要首先直接连接到工作树,这就是设置 GIT_DIR 首先意味着)。

请注意,在子目录中的工作树中  打败了钩子;这就是我所说的“似乎总是在顶级目录中运行”。


5
2017-12-18 19:16





如果您不希望开发人员将某些更改放入存储库,那么一个好的解决方案是锁定存储库并改为使用像Gerrit这样的审查系统。个别变更被推入Gerrit而不得不通过同行评审。

可以拒绝任何添加应该是本地文件的提交,例如API密钥文件或编译目标文件。

然后,开发人员可以修改提交,重写它不包括违规文件,重新提交以供审阅。当它通过审查时,它被挑选到适当的目标分支中。


1
2017-12-18 21:06





另一个解决方案是:

  1. 首先将文件重命名(作为模板),例如将文件添加到repo中。 myFile_template.js
  2. 指示开发人员将模板复制到 myFile.js 并编辑细节
  3. myFile.js 至 .gitignore

仍然不是一个非常强大的解决方案,因为开发人员仍然可以提交您试图隐藏的信息,但至少该文件不会出现在状态列表中。


0
2017-12-13 22:08