Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I mark a committed file as read-only in Git?

Tags:

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:

  • 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.

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; }); 
like image 257
Sean Anderson Avatar asked Dec 18 '14 18:12

Sean Anderson


People also ask

How do I mark a git repository as read only?

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.

How do I hide a commit in git?

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.

How do I open a committed file in git?

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.


2 Answers

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".

like image 164
torek Avatar answered Oct 04 '22 02:10

torek


One possible approach would be to install some server-side hook (e.g. update) that would

  1. check, in pushed references, that the hash of the blob in question remains the same, and
  2. reject any push that contains references in which the hash of the blob in question changes.

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

like image 44
jub0bs Avatar answered Oct 04 '22 04:10

jub0bs