108

I have an existing git repo (a bare one) which has up to this point only been writable by me. I want to open it up to some UNIX user group, foo, so that all members of foo can push to it. I'm aware that I can easily set up a new git repo with:

git init --bare --shared=group repodir
chgrp -R foo repodir

But I need the equivalent operation for an existing repo dir.

ekad
  • 14,436
  • 26
  • 44
  • 46
Pistos
  • 23,070
  • 14
  • 64
  • 77
  • 4
    There’s **[an excellent answer to this question](http://serverfault.com/questions/26954/how-do-i-share-a-git-repository-with-multiple-users-on-a-machine)** over on ServerFault (another StackOverflow site). – Zearin Nov 14 '12 at 15:40

5 Answers5

125

Try this to make an existing repository in repodir work for users in group foo:

chgrp -R foo repodir                 # set the group
chmod -R g+rw repodir                # allow the group to read/write
chmod g+s `find repodir -type d`     # new files get group id of directory
git init --bare --shared=all repodir # sets some important variables in repodir/config ("core.sharedRepository=2" and "receive.denyNonFastforwards=true")
Trevor Boyd Smith
  • 18,164
  • 32
  • 127
  • 177
David Underhill
  • 15,896
  • 7
  • 53
  • 61
  • 14
    I would add that you probably should also set config.sharedRepository = true in the repo's config. http://www.kernel.org/pub/software/scm/git/docs/git-config.html – Pistos Jul 13 '10 at 23:37
  • 2
    This is pretty close to what I was doing on my own, but I wanted to get some external confirmation. Thanks. :) I was also hoping there would be a git clone --shared=group sort of thing, but clone's --shared option does something completely different. – Pistos Jul 13 '10 at 23:41
  • 5
    You can use the `git init --shared` command on an existing repo to set the config value. You also need to do the `chmod` command to get the permissions of the files right. – Spencer Mar 16 '12 at 14:36
  • 1
    To confirm this also helps if you're in a mess because someone has done a `git pull` etc. as root rather than as `www-data` or whatever the owner is and as a result you get `error: insufficient permission for adding an object to repository database .git/objects`. I thought I'd fixed the ownership of all files/directories that were wrong by using `find` and `-type d`/`type -f`, but only this method got rid of the error (prob. because a file in some subdirectory weren't group writeable?) – William Turrell Apr 24 '13 at 20:31
  • @LaurentG - It was a good edit. And the author also [accepted it](http://stackoverflow.com/questions/3242282/how-to-configure-an-existing-git-repo-to-be-shared-by-a-unix-group/3242364#comment3349064_3242364). Any reason behind the roll back? Please see [this Meta post](http://meta.stackexchange.com/q/216212/187824) for more. – Himanshu Jan 15 '14 at 10:34
  • When I set `core.sharedRepository` the new object folders did get group write permission as expected - however not the contained object files themselves. Is that correct ? Wondering since the above repair commands _do_ set the group write permission also on the object files. – Zitrax Mar 14 '16 at 13:10
  • 2
    The user's umask still seems to apply to newly-created files. Is that what you expect? I would think the documentation of `core.sharedRepository` would mention this - it seems useless without users making all of their files group writeable. – Sam Brightman Oct 17 '16 at 12:15
  • how did you created that foo group ? – Sujithrao May 08 '17 at 17:33
53

Merging @David Underhill and @kixorz answers, I made my own (definitive) solution.

It is for bare repos and non-bare repos. There are only little differences between them, but in this way is clearer.

BARE REPOSITORY

cd <repo.git>/                            # Enter inside the git repo
git config core.sharedRepository group    # Update the git's config
chgrp -R <group-name> .                   # Change files and directories' group
chmod -R g+w .                            # Change permissions
chmod g-w objects/pack/*                  # Git pack files should be immutable
find -type d -exec chmod g+s {} +         # New files get directory's group id

where:

  • <repo.git> is the bare repository directory, typically on the server (e.g. my_project.git/).
  • <group-name> is the group name for git users (e.g. users).

NON-BARE REPOSITORY

cd <project_dir>/                         # Enter inside the project directory
git config core.sharedRepository group    # Update the git's config
chgrp -R <group-name> .                   # Change files and directories' group
chmod -R g+w .                            # Change permissions
chmod g-w .git/objects/pack/*             # Git pack files should be immutable
find -type d -exec chmod g+s {} +         # New files get directory's group id

where:

  • <project_dir> is the project directory containing the .git folder.
  • <group-name> is the group name for git users (e.g. users).
Andrea
  • 15,900
  • 18
  • 65
  • 84
  • As Charles said, also do: `chmod g-w objects/pack/*` (if non-bare repository, prepend `.git/`) – Wernight Aug 11 '15 at 07:52
  • here how can we find the group name or how to create the group name? – Sujithrao May 08 '17 at 17:30
  • 'chmod g+s `find . -type d`' raises error `unable to execute /bin/chmod: Argument list too long` – Dr.X Jul 31 '17 at 12:12
  • As @Dr.X noted, `chmod g+s \`find . -type d\`` does not scale. Use `find -type d -exec chmod g+s {} +` – hagello Aug 16 '17 at 18:40
  • I think all the loose objects should also be read-only based on the pre-shared state. Maybe something like `chmod g-w objects/*/*`. I'm not sure about the info subdirectory though since it's empty for this repo. – Eric Sep 27 '17 at 20:42
  • 3
    You can save the hassle of `chmod g+w -R` and `chmod g+w .git/objects/pack/*` by running `chmod g=u` which applies the user's permissions to the group's permission–may they be writable or not. This is more suitable if the repo contains read-only files or Git will create other read-only files some day. – Daniel Böhmer Dec 06 '18 at 13:34
  • @Andrea, for the non-bare repo, shouldn't we `cd .git` before altering permissions? The point is to make the repo shareable, not to alter the working tree file attributes... – Agent Friday Oct 20 '19 at 02:43
49

In the repo dir execute following commands:

git config core.sharedRepository group
chgrp -R foo repodir
chmod -R g+w repodir

Edit: To address frequent confusion, group is an actual keyword, you're not supposed to replace this with the name of the group.

adamkonrad
  • 6,794
  • 1
  • 34
  • 41
  • 26
    Where `group` is NOT the name of the group :) – Pierre de LESPINAY Nov 27 '12 at 09:45
  • 7
    Object and pack files should be immutable; they should have permissions 444 / r--r--r--. – CB Bailey May 07 '13 at 12:42
  • 3
    After trying `git config core.sharedRepository dev` then typing `git config` I get `fatal: bad config value for 'core.sharedrepository' in .git/config` in `git version` `1.7.0.4` (and possibly versions after) – Kzqai Jul 03 '13 at 22:13
  • 3
    `git config core.sharedRepository group` `group` is not the name of the group, but the actual value! – adamkonrad Jul 16 '13 at 15:46
  • 1
    If you've made the mistake of using your group name instead of "group", just open .git/config in text editor and edit the core.sharedRepository line to say "group". – Tom Aug 11 '18 at 11:42
3

This is probably not necessary, but it's worth pointing out that git init --bare --shared also sets the denyNonFastForwards option.

git config receive.denyNonFastForwards true

The meaning of this option is as follows:

receive.denyNonFastForwards

If you rebase commits that you’ve already pushed and then try to push again, or otherwise try to push a commit to a remote branch that doesn’t contain the commit that the remote branch currently points to, you’ll be denied. This is generally good policy; but in the case of the rebase, you may determine that you know what you’re doing and can force-update the remote branch with a -f flag to your push command.

(from http://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration)

nerfologist
  • 761
  • 10
  • 23
1

In addition to the above answers of allowing a group to read/write you also need to add the user to the group (say "foo").

sudo usermod -a -G [groupname] [username]

Note: you will have to first create user if it doesn't exist

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
sarvagya kumar
  • 121
  • 1
  • 8