241

I have a Git repository on a staging server which multiple developers need to be able to pull to. git-init seems to have a flag very close to what I'm looking for: --shared, except I'd like multiple people to pull to that repository, as well. The git-clone's --shared flag does something entirely different.

What's the easiest way to change an existing repository's permissions?

10 Answers10

211

Permissions are a pest.

Basically, you need to make sure that all of those developers can write to everything in the git repo.

Skip down to The New-Wave Solution for the superior method of granting a group of developers write capability.

The Standard Solution

If you put all the developers in a specially-created group, you can, in principle, just do:

chgrp -R <whatever group> gitrepo
chmod -R g+swX gitrepo

Then change the umask for the users to 002, so that new files get created with group-writable permissions.

The problems with this are legion; if you’re on a distro that assumes a umask of 022 (such as having a common users group that includes everyone by default), this can open up security problems elsewhere. And sooner or later, something is going to screw up your carefully crafted permissions scheme, putting the repo out of action until you get root access and fix it up (i.e., re-running the above commands).

The New-Wave Solution

A superior solution—though less well understood, and which requires a bit more OS/tool support—is to use POSIX extended attributes. I’ve only come to this area fairly recently, so my knowledge here isn’t as hot as it could be. But basically, an extended ACL is the ability to set permissions on more than just the 3 default slots (user/group/other).

So once again, create your group, then run:

setfacl -R -m g:<whatever group>:rwX gitrepo
find gitrepo -type d | xargs setfacl -R -m d:g:<whatever group>:rwX

This sets up the extended ACL for the group so that the group members can read/write/access whatever files are already there (the first line); then, also tell all existing directories that new files should have this same ACL applied (the second line).

Hope that gets you on your way.

womble
  • 98,245
138

if you created the repository (or cloned a new bare repo off an existing one) with

$ git init --shared=group 

or

$ git init --shared=0NNN

Git is supposed to handle permissions above and beyond what your default umask provides. At last this is true on my version of Git (1.6.3). Of course this assumes your users are in the same group.

If I needed management of users in multiple groups with varying degrees of read/write however, I'd go with gitosis. I have also heard mention of gitolite (http://github.com/sitaramc/gitolite), a gitosis fork that is suppossed to provide branch level permissions, can't say I've every used it personally though.

57

This has not been said, so I want to quickly add it.

To ensure that permissions issues do not crop their ugly head, make sure to set the following on your git shared repository's config file:

[core]
    sharedRepository = true

This will ensure that your system's "umask" settings are respected.

20

The Git User Manual describes how to share a repository in several ways.

More complicated, though feature-full ways to share repositories are:

We use GitHub for a team of 6 developers.

Roman Byshko
  • 262
  • 2
  • 13
jtimberman
  • 7,665
9

To aggregate the bits and pieces of good advice from the various other answers and comments about setting up a new repo:

If you're setting up a brand new repo myrepo in /srv/git for the group mygroup, this is what you want:

mkdir /srv/git/myrepo.git
chgrp mygroup /srv/git/myrepo.git
git init --bare --shared /srv/git/myrepo.git
  1. the first line creates the repo dir
  2. the second line sets its group to mygroup
  3. the third line initializes a bare repo with the following configuration:
    1. core.bare = true: make it a bare repo
    2. core.sharedrepository = 1 (same as core.sharedrepository = group): the repo directory and all directories later created in it will be managed by git to allow mygroup read, write, and execute permissions (with the sgid bit set as well -- so as to work with users for whom mygroup is not their primary group)
    3. receive.denyNonFastforwards = 1: deny non fast-forward pushes to the repo

If you want to fine-tune the user, group, or other users' permissions, use --shared=0NNN, where NNN are the standard user, group, and other bits for files (the execute and sgid bits on directories will be managed appropriately by git). For example, this allows read and write access to the user, and read-only access to the group (and no access to other):

git init --bare --shared=0640 /srv/git/myrepo.git

This allows read and write access to the user and group (and no access to other):

git init --bare --shared=0660 /srv/git/myrepo.git

This allows read and write access to the user and group, and read-only access to other:

git init --bare --shared=0664 /srv/git/myrepo.git

Note that if you're not going to allow write access to the group, make sure to first use chown to set the owner of the repo, and then run the git init command as that user (to make sure the repo is initialized with the correct owner for all the initial files and sub-directories).

8

Also look at gitolite for hosting your git repository. Gitosis apparently isn't being developed anymore.

mt3
  • 328
6

One way to fix permissions in the shared repository, so users won't have permission problems when pushing, is to create a post-update hook script which will do just that. This should work in any git version.

Suppose you have a shared repository in /myrepo.git. All files in that repository belong to say mysharedgroup. All users pushing to that repository should belong to mysharedgroup also. Now create the following file (changing mysharedgroup to your preferences):

/myrepo.git/hooks/post-update

#!/bin/sh
chmod -R g+w . 2>/dev/null
chgrp -R mysharedgroup . 2>/dev/null
bkmks
  • 69
5

Doing exactly this worked for me, for an existing repository. This takes advice from several answers and comments before:

From your repository parent directory, at the server:

chgrp -R <whatever group> gitrepo
chmod -R g+wX gitrepo
cd gitrepo
find . -type d -exec chmod g+s {} +
git config core.sharedRepository group
2

You can use git-daemon to share the repository. Read the documentation for git-daemon for more information.

EDIT:

Also check this article 8 ways to share your git repository.

Vihang D
  • 640
0

@stevek_mcc answer is the one I was looking for when I googled for this question

git clone --config core.sharedRepository=true