如何在 Git 中将提交的文件标记为只读?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27553551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I mark a committed file as read-only in Git?
提问by Sean Anderson
I have a file which is checked into Git. The file needs to hold an API key, but I do not wish to commit the API key to Git for security reasons. Instead of an API key, I put an explanation of how to generate an API key for each developer to use.
我有一个已签入 Git 的文件。该文件需要保存一个 API 密钥,但出于安全原因,我不希望将 API 密钥提交给 Git。我没有使用 API 密钥,而是解释了如何生成供每个开发人员使用的 API 密钥。
I don't want any developer to accidentally commit their API key and overwrite the basic file.
我不希望任何开发人员意外提交他们的 API 密钥并覆盖基本文件。
I have:
我有:
- Added the file to the
.gitignore
file, but, since it is already committed, this does not do anything. - Ran the command
git update-index --assume-unchanged myFile.js
- Added the command to the explanation file to inform other developers that they should also run this command.
- 将文件添加到
.gitignore
文件中,但是,由于它已经提交,因此没有任何作用。 - 运行命令
git update-index --assume-unchanged myFile.js
- 将命令添加到解释文件中以通知其他开发人员他们也应该运行此命令。
However, I just moved to my laptop, forgot to run the command, and accidentally committed a key to the repo. I'm looking for a more fail-safe method. In essence, I want to commit an initial version of the file to GitHub and then disallow modifications of that file.
然而,我刚搬到我的笔记本电脑上,忘记运行命令,并且不小心提交了一个存储库的密钥。我正在寻找一种更安全的方法。本质上,我想将文件的初始版本提交到 GitHub,然后禁止修改该文件。
Is this possible?
这可能吗?
For reference, the file looks something like:
作为参考,该文件类似于:
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;
});
采纳答案by jub0bs
One possible approach would be to install some server-side hook(e.g. update
) that would
一种可能的方法是安装一些服务器端挂钩(例如update
)
- check, in pushed references, that the hash of the blob in question remains the same, and
- reject any push that contains references in which the hash of the blob in question changes.
- 在推送的引用中检查所讨论的 blob 的哈希值是否保持不变,并且
- 拒绝任何包含相关 blob 哈希更改的引用的推送。
Of course, such a server-side hook would not stop contributors from creating commits (locally, on their machines) that contain a different version of the file. However, after seeing a few of their pushes rejected, they would surely learn the lesson. :p
当然,这样的服务器端钩子不会阻止贡献者创建包含不同版本文件的提交(在本地,在他们的机器上)。不过,在看到他们的几次推送被拒绝后,他们肯定会吸取教训。:p
回答by torek
The answer to the implied subject line question ("can I make git check out a particular file as read-only") is "no, at least not directly", since git only stores a single permissions bit per file: executable, or not-executable. All other bits are set the same for each file.
隐含的主题行问题(“我可以让 git 将特定文件检出为只读吗”)的答案是“不,至少不是直接”,因为 git 只为每个文件存储一个权限位:可执行,或者不- 可执行。每个文件的所有其他位都设置相同。
That said, though, there are a few tricks using hooks. As some commenters suggested, you can test something in a server-side hook to prevent pushes. You can use smudge and clean filters. You can have a post-checkout
hook set the file read-only.
尽管如此,使用钩子还是有一些技巧。正如一些评论者所建议的那样,您可以在服务器端挂钩中测试某些内容以防止推送。您可以使用污迹和清洁过滤器。您可以使用post-checkout
挂钩将文件设置为只读。
The drawback to any and all hooks is that they must be set up for each repository, and users can override them (except for a server-side hook, presuming the user has no direct access to the server).1This is also the advantage to a hook, although for naive users it's probably more drawback than advantage, since git itself won't set up the hooks automatically.
任何和所有挂钩的缺点是必须为每个存储库设置它们,并且用户可以覆盖它们(服务器端挂钩除外,假定用户无法直接访问服务器)。1这也是钩子的优点,尽管对于天真的用户来说,这可能是弊大于利,因为 git 本身不会自动设置钩子。
The post-checkout
hook is probably the most obvious place to set file permissions, since git's documentation includes this bit:
该post-checkout
挂钩可能是最明显的地方设置文件权限,因为Git的文档包括该位:
This hook can be used to ... set working dir metadata properties.
此钩子可用于...设置工作目录元数据属性。
Conveniently, the hook appears to always be run in the top level directory, regardless of where the user is, as long as the user is actually inside the git work tree.2So this very simple hook suffices to change one file to read-only:
方便的是,钩子似乎总是在顶级目录中运行,无论用户在哪里,只要用户实际上在 git 工作树中。2所以这个非常简单的钩子足以将一个文件更改为只读:
#! /bin/sh
# post-checkout hook to make one file read-only
chmod -w path/to/file
(on any system with chmod
anyway, and remember to set the hook up as an executable file).
(chmod
无论如何,在任何系统上,记住将挂钩设置为可执行文件)。
The user must put this hook into his/her repository, in .git/hooks/post-checkout
(though you can commit the file itself into the repository, and then have the user copy or link it into place, perhaps through an auxiliary setup script).
用户必须将此挂钩放入他/她的存储库中.git/hooks/post-checkout
(尽管您可以将文件本身提交到存储库中,然后让用户将其复制或链接到位,也许通过辅助设置脚本)。
1Thus, a server-side hook is the place to go if you want to strictly enforcea policy (this is true in general).
1因此,如果您想严格执行策略(通常情况下是这样),可以使用服务器端挂钩。
2That is, the following defeats the hook:
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
Here, the current working directory is just /tmp
, and there is no way for the hook to figure out what it should be (you can read $GIT_DIR
, but that's not necessarily helpful since the .git
directory need not be directly connected to the work-tree in the first place, and that's what setting GIT_DIR
is meant for in the first place).
在这里,当前工作目录只是/tmp
,钩子无法确定它应该是什么(您可以阅读$GIT_DIR
,但这不一定有帮助,因为.git
目录不需要直接连接到第一个工作树地方,这就是设置GIT_DIR
的初衷)。
Note that being in the work tree, in a sub-directory, does notdefeat the hook; that's what I mean by "appears to always be run in the top level directory".
请注意,在工作树是,在一个子目录,并没有打败挂钩; 这就是我所说的“似乎总是在顶级目录中运行”的意思。
回答by Matt
Another solution is to:
另一种解决方案是:
- Add your file to the repo by first renaming it (as a template), e.g.
myFile_template.js
- Instruct developers to copy the template to
myFile.js
and edit the details - Add
myFile.js
to.gitignore
- 通过首先重命名它(作为模板)将您的文件添加到存储库,例如
myFile_template.js
- 指示开发人员复制模板
myFile.js
并编辑详细信息 - 添加
myFile.js
到.gitignore
Still not a very robust solution, as the developers can still commit the information you are trying to keep hidden, but at least the file won't appear in the status list.
仍然不是一个非常强大的解决方案,因为开发人员仍然可以提交您试图隐藏的信息,但至少该文件不会出现在状态列表中。
回答by Kaz
If you don't want developers to put certain changes into the repository, a good solution is to lock the repository and have instead a review system in place like Gerrit. Individual changes are pushed into Gerrit instead and have to pass peer review.
如果您不希望开发人员将某些更改放入存储库中,一个好的解决方案是锁定存储库并使用 Gerrit 之类的系统。个人更改被推送到 Gerrit 中,并且必须通过同行评审。
Any commit which adds a file that ought to be local, such as an API key file or a compiled object file, can be rejected.
任何添加应该是本地文件的提交,例如 API 密钥文件或编译的目标文件,都可以被拒绝。
The developer can then revise the commit, rewriting it not to include the offending file, re-submit for review. When it passes review, it is cherry-picked into the appropriate target branch.
然后开发人员可以修改提交,重写它以不包含违规文件,重新提交以供。当它通过时,它会被挑选到适当的目标分支中。