Thursday, May 17, 2012

Gitolite... my new shiny penny

At my current client engagement, I'm serving as the build-guy and all around code librarian.  I'm managing 35 or so git repositories... keeping them tidy and organized.

Since the client seems to heavily utilize consultant help, they have a veritable revolving door of staff.  Before my arrival they decided to purchase and use a tool called gitorious to aid in managing the repositories and access to them.  It's pretty much like a private github.  It has all kinds of features including web-based management of users/keys, browse-able git logs, etc.  They have it running as an appliance on a virtual server here at the office.



It works pretty well and I've embraced it because it's the "officially-blessed-by-enterprise-architecture" tool.

It's not without it's drawbacks though:

  • In it's default configuration, EVERYONE/ANONYMOUS has READ access to ALL repositories.
  • Gitorious is heavily integrated with git's hooks, so if you want to add your own hooks to a repository, you're pretty much out of luck... unless you like tampering with their code - good luck with that.
  • If you don't want use their appliance and want to install it yourself, it's not all that straight forward.
  • The UI isn't really that intuitive.  For example if you want to see a list of tags for a repository, you have to drill into a branch rather than seeing them at the repository level.
  • It costs money if you want to have your own on-site copy.
All that said, I started looking around for alternatives for managing medium to large numbers of git repositories (more than 5'ish) both for my own stuff as well as for future clients.

In looking around, I found a tool called gitolite.  Gitolite seem to provide all the features that I want/need and has the benefits of being simple/easy to implement as well as being opensource/free.

Gitolite doesn't have a user interface.  You mange it with... what else... git!

Installation is easy

If you're running on Ubuntu, you're only a command away from installation:

steve@ubuntu64 ~ $ sudo apt-get install gitolite

That get's app installed and ready to configure.

Configuration is easy too

Instead of housing gitolite on my personal account (which you could easily do... I just choose not to), I created an account for it called git.

steve@ubuntu64 ~ $ sudo adduser git
Adding user `git' ...
Adding new group `git' (1002) ...
Adding new user `git' (1002) with group `git' ...
Creating home directory `/home/git' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for git
Enter the new value, or press ENTER for the default
        Full Name []: Git Repository Home
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] y
steve@ubuntu64 ~ $

After creating the account, you'll want to copy your public key to the git account's home directory for the one and only step of initial gitolite configuration.

steve@ubuntu64 ~ $ sudo cp .ssh/id_rsa.pub /home/git/steveb.pub
steve@ubuntu64 ~ $ sudo chown git.git /home/git/steveb.pub
steve@ubuntu64 ~ $

Now we're ready to do the initial configuration.  You'll need to become the git account to do it.

steve@ubuntu64 ~ $ su - git
Password:
git@ubuntu64:~$

Then you'll want to issue the command gl-setup from the bash prompt, passing in the key you just copied.

git@ubuntu64:~$ gl-setup steveb.pub

It will prompt you to edit the default .gitolite.rc file, but don't change anything, it's fine as it is for now.  You may have a need to change it in the future but I haven't so far.  Just save and quit out of your editor without changing anything.

The default settings in the rc file (/home/git/.gitolite.rc) are fine for most
people but if you wish to make any changes, you can do so now.

hit enter...
creating gitolite-admin...
Initialized empty Git repository in /home/git/repositories/gitolite-admin.git/
creating testing...
Initialized empty Git repository in /home/git/repositories/testing.git/
[master (root-commit) 09aad52] start
 2 files changed, 6 insertions(+)
 create mode 100644 conf/gitolite.conf
 create mode 100644 keydir/steveb.pub
git@ubuntu64:~$

That's it.  Gitolite is all set up and ready to use!

git@ubuntu64:~$ exit
logout
steve@ubuntu64 ~ $

Using gitolite is a piece-o-cake


Managing your git repositories with gitolite is done entirely by manipulating a git repository called gitolite-admin.  First let's use gitolite to create a new repository.  Step one:  clone the gitolite-admin repository from your system:

steve@ubuntu64 ~ $ cd dev
steve@ubuntu64 ~/dev $ git clone git@localhost:gitolite-admin.git
Cloning into 'gitolite-admin'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
steve@ubuntu64 ~/dev $

You'll notice that the gitolite-admin clone has a pretty simple directory structure.

steve@ubuntu64 ~/dev $ cd gitolite-admin
steve@ubuntu64 ~/dev/gitolite-admin(master) $ ls -la
total 20
drwxr-xr-x  5 steve steve 4096 May 17 09:23 .
drwxrwxr-x 13 steve steve 4096 May 17 09:23 ..
drwxrwxr-x  2 steve steve 4096 May 17 09:23 conf
drwxrwxr-x  8 steve steve 4096 May 17 09:24 .git
drwxrwxr-x  2 steve steve 4096 May 17 09:23 keydir
steve@ubuntu64 ~/dev/gitolite-admin(master) $

It has two directories: conf and keydir.  The conf directory contains a file called gitolite.conf.  You edit the gitolite.conf file to create repositories and manage permissions to those repositories.

steve@ubuntu64 ~/dev/gitolite-admin(master) $ ls -l conf
total 4
-rw-rw-r-- 1 steve steve 92 May 17 09:23 gitolite.conf
steve@ubuntu64 ~/dev/gitolite-admin(master) $

The keydir directory is where you should place public key files of the users you want to grant access to repositories.  You'll notice that the public key you copied for your self is already there!

steve@ubuntu64 ~/dev/gitolite-admin(master) $ ls -l keydir
total 4
-rw-rw-r-- 1 steve steve 391 May 17 09:23 steveb.pub
steve@ubuntu64 ~/dev/gitolite-admin(master) $

Let's add that new repository.  To do so, simply edit the conf/gitolite.conf file with your favorite text editor.

steve@ubuntu64 ~/dev/gitolite-admin(master) $ vi conf/gitolite.conf

Add the following lines to it:

repo    gitolite-admin
        RW+     =   steveb
repo    testing
        RW+     =   @all
repo my_cool_new_repository
RW+ =   steveb

The two new lines in the file establish that you want to add a new repository named my_cool_new_repository and that you want to grant the user with the public key file steveb.pub full READ/WRITE/REFEDIT permissions.

Save the file. Commit it.  Then push it back to the repository origin.

steve@ubuntu64 ~/dev/gitolite-admin(master) $ git add .
steve@ubuntu64 ~/dev/gitolite-admin(master) $ git commit -m"Added new repository my_cool_new_repository"
[master 393ef15] Added new repository my_cool_new_repository
 1 file changed, 3 insertions(+)
steve@ubuntu64 ~/dev/gitolite-admin(master) $ git push
Counting objects: 7, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 433 bytes, done.
Total 4 (delta 0), reused 0 (delta 0)
remote: creating my_cool_new_repository...
remote: Initialized empty Git repository in /home/git/repositories/my_cool_new_repository.git/
To git@localhost:gitolite-admin.git
   09aad52..393ef15  master -> master
steve@ubuntu64 ~/dev/gitolite-admin(master) $

Gitolite sees your change to the conf/gitolite.conf file.  It then creates a new blank, bare git repository called my_cool_new_repository.git.  It also ensures that the steveb.pub file has the appropriate access to the git account (check out the git account's ~/.ssh/authorized_keys).

That's it.  Your new repository is ready to clone!

steve@ubuntu64 ~/dev/gitolite-admin(master) $ cd ..
steve@ubuntu64 ~/dev $ git clone git@localhost:my_cool_new_repository.git
Cloning into 'my_cool_new_repository'...
warning: You appear to have cloned an empty repository.
steve@ubuntu64 ~/dev $ cd my_cool_new_repository/
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ date > file1.txt
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ git add .
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ git commit -m"Added file1.txt"
[master (root-commit) 90e1635] Added file1.txt
 1 file changed, 1 insertion(+)
 create mode 100644 file1.txt
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 257 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@localhost:my_cool_new_repository.git
 * [new branch]      master -> master
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $

Adding/removing user access is as simple as adding/removing key files from the keydir directory, updating the conf/gitolite.conf file and pushing.

The gitolife.conf file, while very simple, is incredibly powerful.  It supports groups.  Also, it will not only allow you to control access to git repositories, but will also allow you to assign permissions to branches and tags with regular expressions.  Take a look at the documentation for much more info.