【问题标题】:How can I mark a committed file as read-only in Git?如何在 Git 中将提交的文件标记为只读?
【发布时间】:2015-12-14 06:08:20
【问题描述】:

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

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

我有:

  • 已将文件添加到 .gitignore 文件中,但由于它已提交,因此不会执行任何操作。
  • 运行命令git update-index --assume-unchanged myFile.js
  • 将命令添加到说明文件中,以通知其他开发人员他们也应该运行此命令。

但是,我刚搬到我的笔记本电脑上,忘记运行命令,并且不小心提交了 repo 的密钥。我正在寻找一种更安全的方法。本质上,我想将文件的初始版本提交到 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;
});

【问题讨论】:

  • 如何使用server-side hookpre-receiveupdate)检查相关文件的哈希值是否保持不变并拒绝任何修改该文件的推送?
  • @Jubobs 这看起来像是要走的路。您能否再次回复而不是评论,我会接受?谢谢。 (顺便说一句,这不适用于 GitHub,但它确实回答了我的问题。)
  • 今天,出于同样的原因,我问了同样的问题,人们认为我疯了。不过,看起来这是 git 用户的需求! stackoverflow.com/questions/69799488/…

标签: git


【解决方案1】:

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

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

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

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

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

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

#! /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 的初衷)。

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

【讨论】:

    【解决方案2】:

    一种可能的方法是安装一些server-side hook(例如update

    1. 在推送的引用中检查相关 blob 的哈希值是否保持不变,并且
    2. 拒绝任何包含相关 blob 哈希更改的引用的推送。

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

    【讨论】:

      【解决方案3】:

      另一种解决方案是:

      1. 首先将文件重命名(作为模板)将文件添加到 repo,例如myFile_template.js
      2. 指示开发者将模板复制到myFile.js并编辑详细信息
      3. myFile.js 添加到.gitignore

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

      【讨论】:

        【解决方案4】:

        如果您不希望开发人员将某些更改放入存储库,一个很好的解决方案是锁定存储库并使用 Gerrit 等审核系统。个别更改会被推送到 Gerrit 中,并且必须通过同行评审。

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

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

        【讨论】:

        • 我们如何锁定目录?
        • @snwfdhmp 我不知道;我们在说什么?
        猜你喜欢
        • 2019-07-22
        • 2021-07-17
        • 2018-04-24
        • 2011-05-23
        • 1970-01-01
        • 2019-08-21
        • 2023-03-11
        • 2012-06-26
        • 2019-03-20
        相关资源
        最近更新 更多