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.
I don't want any developer to accidentally commit their API key and overwrite the basic file.
I have:
.gitignore
file, but, since it is already committed, this does not do anything.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.
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; });
Open the GitLab webinterface and go to the repository you want to set to read-only. Choose Settings > Repository. Expand Protected Branches. Add the master branch and set Allowed to merge and Allowed to push to No one.
Hide commit history on Git Branch First, create a new temporary branch and checkout. Now, add all the current files to this temporary branch. Create a new commit. Rename the temporary branch to your old branch name.
To add and commit files to a Git repository Create your new files or edit existing files in your local project directory. Enter git add --all at the command line prompt in your local project directory to add the files or changes to the repository. Enter git status to see the changes to be committed.
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.
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.
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).1 This 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.
The post-checkout
hook is probably the most obvious place to set file permissions, since git's documentation includes this bit:
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.2 So this very simple hook suffices to change one file to read-only:
#! /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).
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).
1Thus, a server-side hook is the place to go if you want to strictly enforce a policy (this is true in general).
2That is, the following defeats the hook:
$ 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).
Note that being in the work tree, in a sub-directory, does not defeat the hook; that's what I mean by "appears to always be run in the top level directory".
One possible approach would be to install some server-side hook (e.g. update
) that would
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With