One of my latest projects was setting up the Git source code management system on a customer's server, so that different developers can have different access rights to repositories. How to do that?
For the really simple case of one set of repositories with r/w access to every developer in your organization, you can use a git server, with or without a dedicated user, with or without SSH keys [source]. For the complex case with even intra-repository rights management, there is Gitolite; or Gitosis, but that is no longer maintained [source]. But what is the simplest solution for the middle ground: multiple users, and giving each one access to a potentially different set of repositories?
Here's a solution for that – I haven't seen it documented anywhere, but I guess it's quite obvious. I simply extend the outta-the-box git server scenario by running multiple git servers in parallel, each for one (non-intersecting) set of repositories with one (potentially intersecting) set of developers who get r/w access. So for example, you can have a setup like this:
- team 1
- repositories: project 1, project 2
- developers with access: Alice, Bob, Andrew
- team 2
- repositories: project 3
- developers with access: Alice, Juan
- team 3
- repositories: project 4, project 5
- developers with access: Juan
Setting up a team
For every team, you set up one dedicated user and git server on your host. You can have as many servers as you want, and adding one always follows this procedure. Let's assume we want to set up a team devteam1.
- Create a new user and set a password for it. Say you want to name the user devteam1, then execute:
- In /etc/passwd, change devteam1's shell to be
/usr/bin/git-shell (or wherever it is on your host – see
which git-shell). This prohibits SSH access with this user, but allows git commands.
Adding a developer to a team
Say you want add developer Alice to your team devteam1, which means giving her r/w access to all repositories of devteam1. The simplest solution is to hand out the password for system user devteam1 to the new developer. This requires however to enter it on every commit. (If you want to avoid this, the usual and widely documented method if to use SSH keys with git.)
Note that using one shared user account for writing to your remote repository does not mean that commits from all the developers will use the same author information. Instead, the password needed for
git push just is for transferring your commits. Your commits have been made earlier, in your local git repository, using the author information configured in git.
You can determine git's author information by looking at user.name and user.email in
git config --list (potentially overwritten in environment variables GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL [source]). You can configure this author information for your user in ~/.gitconfig on your local computer, and if needed override it in .git/config per repository, by adding a section like this there:
name = Alice Example
email = firstname.lastname@example.org
Adding a repository to a team
Say you want to add repository project1 to team devteam1. On your server, do this:
git init --bare
chmod -R u=rwX,g=rX,o= .
chown -R devteam1:devteam1 .
git init --bare creates a "bare" repository, which means one that stores all the code in objects, but without having a working directory (the set of source files a developer will work with on her local computer). On your local computer, the git repository resides in a .git subdirectory, while a "bare" repository is created in the current directory, not within a .git one.
chown commands make sure the devteam user is the one with write access to the repository; else, git push commands involving this repository (using email@example.com:/home/devteam1/project1.git) would result in this error message: "error: insufficient permission for adding an object to repository database ./objects" [source]. They also make sure no other user has access, not even nread access.
- Note that read and read/write access to git repositories on the server is controlled by the file permissions of this repository's files. So rights management is effectively just Unix system file rights management: Every Unix system user with read access to these files can be used in a git command to read (clone and pull) the repository. Every Unix system user with write access can be used in a git push command. So if you want to create a world-readable repository, make its files world-readable. If you don't want the simple "team -> repositories" hierarchy we use here, you can instead create a group with r/w access for every repository on the server, a system user per developer, and add that user to all groups of repositories that you want him / her to access r/w.
Working with your repositories
Say you want to access a repository project1 that belongs to devteam1, and your server is example.com:
- Cloning the git repository to your local computer:
git clone firstname.lastname@example.org:/home/devteam1/project1.git. This creates a local directory project1. Go there and do your changes to your code.
- Getting and merging changes from the repository:
- Committing your changes to the repository:
git add .; git commit -m "Commit message."; git push; You will be asked for the password of user devteam1 on the server.