Linode Library Home
Linode Library RSS Feed
Home :: Linux Tools :: Version Control
Print View View Source

Git Source Control Management

Published: Friday, September 4th, 2009 by Sam Kleinman

Git is a source control management platform that allows developers of text-based content, primarily software, to collaborate on a single body of code. Git was originally developed by Linus Torvalds to manage the source code for the Linux kernel, but it has since matured a great deal and many different kinds of developers have taken to using git for managing a diverse assortment of projects and use cases.

Git is a "distributed version control system" (DVCS), and is thus similar to programs like Bazaar (bzr), Mercurial (hg), and Darcs, while being substantively different from conventional version control systems like RCS, CVS, and Subversion (svn). Git allows every user to have a complete and independent working copy of a repository with a full change history of the entire repository, which allows users and groups of users to collaborate with minimal infrastructure including offline-workflows and in the manner which is most conducive to their productivity. Because git is very fast and makes the process of managing "branches" (e.g. different and divergent branches of the same code base) very painless and "low cost." Git enables all contributors to work on a code base in whatever manner is most comfortable for them, while still persevering their ability to interact with other collaborators.

This document provides a basic introduction to distributed version control with git, instructions for installing and getting started with git, as well as information on how to set up git web on your server to browse repositories on the web. It also includes instructions for using gitosis to manage git hosting in a secure and straightforward manner.

Contents

Installing Git

Make sure your package repositories and installed programs are up to date by issuing the following commands:

apt-get update
apt-get upgrade --show-upgraded

Because git uses a "distributed" architecture, every repository and copy of git can act as a server and provide remote access, as well as providing local access to a repository. We will probably want to install git on our local machines before we begin working with git on the server. If you're running the same operating system on your local machine as your Linode, follow the same instructions on both machines. If you're using Mac OS X on your local machine, you can install using MacPorts by issuing the command "port install git-core" or by using the Mac OS X git installer. If you're using Microsoft Windows, we recommend using mySysGit. To install git on popular Linux-based operating systems follow the directions below:

On Debian and Ubuntu systems install git with the following command:

apt-get install git-core

CentOS users will have to enable the EPEL repository first using the following command:

rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm

On CentOS and Fedora systems install git with the following command:

yum install git

On Arch Linux install git with the following command:

pacman -Sy git

On Gentoo systems, install git with the following command:

emerge 'ask --verbose dev-util/git

As every git repository is fully independent and functional without the need for a centralized server as is the case with CVS and Subversion much of the content of this guide will be applicable for both local and remote instances of git.

Distributed Version Control

If you're new to git, there are a few key concepts that you might find helpful:

Git makes branching incredibly simple and inexpensive. Branches represent two different and diverging copies of a single point in the history of a body of code or repository. Indeed, because git allows users to maintain their own fully independent repositories, all repositories function like branches, and git is very good at performing fairly complex merges very quickly. Most of the time, when git merges two diverging branches, the merge process is transparent and automatic. As a result of this capability, branches within the repository are easily created and can be used to allow developers to experiment with a code base, while tracking the history of that experimentation. Meanwhile, other collaborators may continue to use their own branches and the mainline "master" branch as normal.

The distributed and decentralized design of git is sometimes a bit hard to grasp. As every repository is fully functional and contains a complete "clone" of a project's history, there is no real need for a centralized git server unless your workflow depends on a centralized repository. While some projects may publish a centralized repository, in point of fact much of the actual work on code happens in smaller, ad-hoc repositories that publish change sets that are later incorporated into the "mainline" repository. Some git workflows also revolve around the exchange of patches over email. In general, as you're using git, it is important to remember that retrieving content from remote repositories (a practice known as "pulling") is not a parallel operation compared with publishing a change set to a remote repository (known as "pushing"). While you will likely be pulling changes quite regularly, publishing commits will likely happen much more infrequently. Also, to prevent complicated merges, it's always a good idea to pull changes from a remote repository before publishing changes to that repository.

Final note: As there is no single, unified, linear history in a git repository as a result of often frequent branches and merges, commits cannot be identified by ordered numbers. Rather, every object in a git database (directory trees, file objects, and commits) is defined by a SHA-1 hash. If there is a particularly important commit, save a copy of the SHA-1 hash for that commit, as it can be used to identify objects shared between "clones" of the same repository.

Basic Git Commands

There are a great deal of git commands that you may need to use at some point, but the following list provides a greatly condensed crash course on the 12 commands which represent the overwhelming majority of commands used.

There are many other commands which are beyond the scope of this document. Use git help and git help COMMAND to access the manual pages for a specific git command.

You may find the following aliases helpful additions to your .bashrc or .bash_profile files, for easier git usage from the command line:

alias gs='git status'
alias ga='git add'
alias grm='git rm'
alias gmv='git mv'
alias gph='git push'
alias gpl='git pull'

The following functions are also helpful for quickly committing and cloning repositories as needed:

gc() { git commit -m "$*" }

gca() { git commit -am "$*" }

gclone(){ git clone ssh://[username]@[domain]/srv/git/$1.git }

The commit functions allow you to quickly create a commit object and message by placing everything following gc in the commit message. The final command requires you to fill in a few variables regarding the location of your git repositories, but is quite useful if you host a number of repositories which aren't mirrored locally on all of your machines.

Providing Remote Access to Git Repositories

One of the cardinal rules of using git is that you should never push to a non-bare repository, as git's object database becomes out of sync and confused by the working copy. As a result, published repositories, particularly repositories that people will push changes to, should be created as "bare" repositories with the "git init --bare" command.

The simplest way to host "bare" remote git repositories is to put those repositories in a directory, /srv/git/ for example, making sure that the repositories are "owned" by a group that all of your git commiters have access to. If every git committer has a shell account with access to these repositories, then they will be able to clone and push to a URL in the following form:

ssh://squire@collab.example.com/srv/git/dance-notes.git/

In this example, "squire" is the username, "collab.example.com" is the hostname for the machine where the repositories reside, and "/srv/git/dance-notes.git/" is the path of the repository.

If you have a number of git repositories or don't want to give out shell accounts to all people with "push access" to the repositories, you can use a tool called gitosis to provide secure access to git repositories over SSH with a single shell account.

On Debian 5.0 (Lenny) and Ubuntu 9.04 (Jaunty), installing gitosis can be accomplished with the following command:

apt-get install gitosis

On Gentoo Linux, issue the following commands to install gitosis:

echo "dev-util/gitosis" >> /etc/portage/package.keywords
emerge -av dev-util/gitosis

On Gentoo systems, note that repositories hosted by gitosis will be located in /var/spool/gitosis/repositories.

On Arch Linux you can use this PKGBUILD script to install gitosis.

Some more recent Fedora and CentOS systems may have gitosis packages, which you can install with:

yum install gitosis

If you're not using a distribution that has packages for gitosis, you can download the gitosis source yourself and follow the complete directions for installing gitosis.

Once gitosis is installed, you will want to copy your SSH public key to /tmp/key.pub on the server and then issue the following command:

sudo -H -u git gitosis-init < /tmp/key.pub

You may have to install sudo, if you have not done so already. By default, repositories will be created in the /home/git/repositories/ directory

On your local machine, you'll now be able to clone the gitosis admin repository with the following command:

git clone git@example.org:gitosis-admin.git

The gitosis-admin repository contains a directory named keydir/ and a file named gitosis.conf.

The keydir/ contains the SSH public keys for your users in files named in the convention of [username].pub. Each user of your git repositories will have their own file in keydir/; the username is for internal gitosis use, and needn't correspond with any shell username.

The gitosis.conf file contains a set of access control rules that can be used to provide people access to a particular repository. An access control block looks like this:

[group morris]
    writable = wiki mail notes
    members = squire fore bag rag

This block gives the users (e.g. keys in the keydir/) "squire," "fore," "bag," and "rag" access to the wiki, mail, and notes repositories. Note that repositories in the "writable" list needn't exist before a user pushes to them, as gitosis will create the new repositories as needed.

To create a new repository, just add it to the writable list of a gitosis group. All repositories will have "clone" or "remote" URLs in the following form:

git@[domain.tld]:[reponame].git

You may have as many "groups" as you need to support your workflow.

Providing a Web Interface with Gitweb

If you want a web-based git repository browser, consider using the gitweb application which comes bundled with git. Gitweb is a cgi-based Perl application and runs on your existing web server. This section provides an example configuration and instruction for installing gitweb for the first time.

Configure and Install Gitweb

Most installations of git include a copy of gitweb. However, some distributions provide separate gitweb packages. To run gitweb you need the gitweb application file gitweb.cgi and the optional (but recommended) support files gitweb.css, git-favicon.png, and git-logo.png. You will also need to create a gitweb_config.perl file, but an example of this is contained below.

For Debian and Ubuntu Systems you can install gitweb with the following command:

apt-get install gitweb

The gitweb files will be located at /usr/lib/cgi-bin/gitweb.cgi and /usr/share/gitweb/.

In Gentoo systems, you must build git with the perl and cgi flags by adding "dev-util/git perl cgi" to your /etc/portage/package.use file. Next, you may emerge the required package with "emerge dev-util/git". Gitweb files will be located in /usr/share/git/gitweb.

Arch Linux systems don't package gitweb with their git package. If your distribution doesn't include gitweb, you should download git's own git repository, or a release of git to get the needed gitweb files.

CentOS systems use the command "yum install gitweb". The files are located in /var/www/git/.

Copy the files listed above into a web accessible location. For the purpose of this example, we assume that the location of your gitweb instance will be /srv/www/example.com/public_html/git/. Debian and Ubuntu users would issue the following command sequence:

cp /usr/lib/cgi-bin/gitweb.cgi /srv/www/example.com/public_html/git/
cp -R /usr/share/gitweb/* /srv/www/example.com/public_html/git/

Users of other operating systems should modify this command to reflect the location of the gitweb files on their systems. Then, create a gitweb_config.perl file in location of your gitweb instance. Consider following example, and modify this configuration as needed.

File:/srv/www/example.com/gitweb_config.perl

# where's the git binary?
$GIT = "/usr/bin/git";
$git_temp = "/tmp";

# where's our projects?
$projectroot = "/srv/www/example.com/public_html/git/";
# $projects_list = $projectroot;
@git_base_url_list = qw(http://example.com/git/ git://example.com/git);

# what do we call this site
$site_name = "git repositories";
$home_text = "indextext.html";

# what do we call our projects in the ui?
$home_link_str = "public repositories";
$projects_list_description_width = "250";
# $feature{'pathinfo'}{'default'} = [1];

# where are the files we need for web display?
@stylesheets = ("gitweb.css");
$logo = "git-logo.png";
$favicon = "git-favicon.png";

To include a repository into your git web simply create a symbolic link from the repository, located in /srv/git/ (for example), to the public gitweb folder, located in /srv/www/example.com/public_html/ (for example) with the following command:

ln -s /srv/git/morris.git/ /srv/www/example.com/public_html/morris.git

Thus presence in a public gitweb can be maintained separately from the repositories themselves, via symbolic links.

.htaccess Configuration

Use the following configuration in the gitweb directory's .htaccess file:

Options +ExecCGI
AddHandler cgi-script .cgi
DirectoryIndex gitweb.cgi

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.* /gitweb.cgi/$0 [L,PT]

This removes unnecessary clutter from URLs and enables CGI access to the gitweb instance.

Creative Commons License

This guide is licensed under a Creative Commons Attribution-NoDerivs 3.0 United States License.

Last edited by Amanda Folson on Monday, May 23rd, 2011 (r2070).