Reputation: 16013
I'm using Git with a team. We have set up a bare repository that we're treating as our "central" repository on a private *nix server.
To make sure that only my collaborators and I can use the repository, I created a user group on the server for us:
$ mkgrp ourproject
And then created a bare Git repo on the server, setting its permissions and group appropriately:
$ newgrp ourproject # Create new files as the correct group
$ umask 007 # Members of the group and I can do anything to the files; no one else can
$ git init --bare
$ ls -l
drwxrwx--- 2 knorth ourproject 2 May 13 16:15 branches
-rwxrwx--- 1 knorth ourproject 66 May 13 16:15 config
-rwxrwx--- 1 knorth ourproject 73 May 13 16:15 description
-rwxrwx--- 1 knorth ourproject 23 May 13 16:15 HEAD
drwxrwx--- 2 knorth ourproject 10 May 13 16:15 hooks
drwxrwx--- 2 knorth ourproject 3 May 13 16:15 info
drwxrwx--- 15 knorth ourproject 15 May 18 20:48 objects
drwxrwx--- 4 knorth ourproject 4 May 13 16:15 refs
So far, so good.
Whenever I push to the Git repository, though, the permissions of the new objects in the repository are set to -r--------
instead of -rwxrwx---
, as I expected. In addition, the new files are being assigned to a group called grad
, one of the other groups I belong to, instead of the ourproject
group.
On my local machine, I push the changes:
Kevins-MacBook-Pro:cloned-repo ThePondermatic$ git push
Password:
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 111.01 KiB | 0 bytes/s, done.
Total 9 (delta 0), reused 0 (delta 0)
To knorth@server.net:/home/repo/location
11fb73c..d9c0db4 master -> master
Then, on the server:
$ ls -lR # Show the permissions for all files in the bare repo
.:
total 20
drwxrwx--- 2 knorth ourproject 2 May 13 16:15 branches
-rw-rw---- 1 knorth ourproject 66 May 13 16:15 config
-rw-rw---- 1 knorth ourproject 73 May 13 16:15 description
-rw-rw---- 1 knorth ourproject 23 May 13 16:15 HEAD
drwxrwx--- 2 knorth ourproject 10 May 13 16:15 hooks
drwxrwx--- 2 knorth ourproject 3 May 13 16:15 info
drwxrwx--- 15 knorth ourproject 15 May 18 20:48 objects
drwxrwx--- 4 knorth ourproject 4 May 13 16:15 refs
./branches:
total 0
./hooks:
total 26
-rwxrwx--- 1 knorth ourproject 452 May 13 16:15 applypatch-msg.sample
-rwxrwx--- 1 knorth ourproject 896 May 13 16:15 commit-msg.sample
-rwxrwx--- 1 knorth ourproject 189 May 13 16:15 post-update.sample
-rwxrwx--- 1 knorth ourproject 398 May 13 16:15 pre-applypatch.sample
-rwxrwx--- 1 knorth ourproject 1704 May 13 16:15 pre-commit.sample
-rwxrwx--- 1 knorth ourproject 1239 May 13 16:15 prepare-commit-msg.sample
-rwxrwx--- 1 knorth ourproject 4951 May 13 16:15 pre-rebase.sample
-rwxrwx--- 1 knorth ourproject 3611 May 13 16:15 update.sample
./info:
total 2
-rw-rw---- 1 knorth ourproject 240 May 13 16:15 exclude
./objects:
total 39
drwx--x--x 2 knorth grad 3 May 13 16:18 11
drwx--x--x 2 knorth grad 3 May 13 16:18 21
drwx--x--x 2 knorth grad 3 May 18 20:48 4b
drwx--x--x 2 knorth grad 3 May 18 20:48 65
drwx--x--x 2 knorth grad 3 May 18 20:48 69
drwx--x--x 2 knorth grad 3 May 18 20:48 7e
drwx--x--x 2 knorth grad 3 May 18 20:48 87
drwx--x--x 2 knorth grad 3 May 18 20:48 cd
drwx--x--x 2 knorth grad 3 May 18 20:48 d6
drwx--x--x 2 knorth grad 4 May 18 20:48 d9
drwx--x--x 2 knorth grad 3 May 13 16:18 e3
drwxrwx--- 2 knorth ourproject 2 May 13 16:15 info
drwxrwx--- 2 knorth ourproject 2 May 13 16:15 pack
./objects/11:
total 2
-r-------- 1 knorth grad 138 May 13 16:18 fb73c05ea22ab9c90a93795fb3f9c2797d0fea
./objects/21:
total 2
-r-------- 1 knorth grad 62 May 13 16:18 ed7bc969b55a4bf57da33c868ac3b61f94d75b
./objects/4b:
total 2
-r-------- 1 knorth grad 148 May 18 20:48 626af7d3bd4d8874899fca47498ccb40279dde
./objects/65:
total 2
-r-------- 1 knorth grad 125 May 18 20:48 82534615eb3f6b54114d8649cf68d8af15aa8b
./objects/69:
total 21
-r-------- 1 knorth grad 20518 May 18 20:48 4a8974a043e616448faa43bfe38a627738436a
./objects/7e:
total 3
-r-------- 1 knorth grad 1781 May 18 20:48 9e723b7b9f19170d93c4561592de6a9493cc6e
./objects/87:
total 2
-r-------- 1 knorth grad 61 May 18 20:48 27591210bd17c85f46f9fde043fe8cd25c11b0
./objects/cd:
total 2
-r-------- 1 knorth grad 153 May 18 20:48 327eec7c8f0a310a6da1283212679cc3baa229
./objects/d6:
total 2
-r-------- 1 knorth grad 63 May 18 20:48 a2be2b03ed954b5aa80349357e2b5a185122dd
./objects/d9:
total 94
-r-------- 1 knorth grad 93619 May 18 20:48 9733e331131b8bfccc817442bbd1959a8d37fb
-r-------- 1 knorth grad 387 May 18 20:48 c0db4b3d0309bea0370baeb9781994894fd16e
./objects/e3:
total 3
-r-------- 1 knorth grad 802 May 13 16:18 0616da1903944069de5b4d6d64c1ac0dead823
./objects/info:
total 0
./objects/pack:
total 0
./refs:
total 6
drwxrwx--- 2 knorth ourproject 3 May 18 20:48 heads
drwxrwx--- 2 knorth ourproject 2 May 13 16:15 tags
./refs/heads:
total 2
-rw------- 1 knorth grad 41 May 18 20:48 master
./refs/tags:
total 0
Notice that most of the files in the objects
directory now have -r--------
permissions and belong to the grad
group. This is not the behavior I was expecting, and it means that whenever my collaborators try to git pull
or git clone
from the repo, they get the following error:
fatal: '/home/repo/location' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
How can I configure the Git repository or the *nix environment it is stored in so that:
-rwxrwx---
permissions for files and drwxrwx---
permissions for folders, andourproject
group instead of the grad
group?Upvotes: 0
Views: 1250
Reputation: 489808
Group ownership is up to the file system containing the git repository. Different servers assign group IDs based on different criteria. One common method is to use the group ID of the containing directory always; another is to use the primary group ID of the creating process always; and a third, compromise, method picks which method to use based on the setgid bit of the containing directory. See this description for Linux for instance. You probably want to set the "setgid" bit of the directory that will contain your bare repos (systems that use this bit automatically propagate the setting to new directories, otherwise it would be too painful to use).
Group write permission is controlled by git's core.sharedRepository
setting. See the git-config
documentation for details, but in short you want to set this to group
or true
. This is primarily needed for container directories (e.g., objects/
and objects/a7/
, refs/
, and so on) within a git repository (see below).
The execute bit of each source-controlled file is set per-file, and is set by git based on the permissions of files at the time they're added to the index. If any execute bit is set at that time, the file is stored as mode 0755
, otherwise it is stored as mode 0644
. (Changing the mode and re-adding a file will give you a "mode changed, no contents changed" diff indication, for instance.) While this looks like rwxr-xr-x
or rw-r--r--
, git really only cares about a single flag, "should this file have its execute permission set when extracted". The decision as to which "x" bits to set (user, group, and/or other) occurs at check-out time, based on the user's umask.
Underlying objects and pack files (inside the .git
directory, or more visible but the same effect in a bare repo) are kept read-only and are only made temporarily write-able as needed (in fact, by creating a new file, writing all the new data to the new file, and then swapping the files "in place" using rename
to obtain atomicity—this new-file-creation is why the group ownership and directory-permissions are important, if a repository is shared by group permissions). Keeping the git database files read-only presumably prevents accidental overwriting. (This same read-only rule is not applied to files like refs/heads/master
, probably because in the early days of git, these files were written directly with echo
commands and the like, rather than the fancy create-write-rename trick.)
There is no reason to make a config file executable and git simply won't do that.
Permissions on hooks are set by whoever sets up the hooks. Git does not alter these at all (nor source-code-control them), it simply checks whether the hook can be run: if it can, it is.
Upvotes: 4