1. Preface

Git is an open source, distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Read the wikipedia article on Git to get an (not so short) overview.

Note This document is work progress. Your feedback (mail to mika@grml.org) is highly appreciated!

2. Installation of Git

Notice: this section is specific for Debian (based) systems.

2.1. The core system

# aptitude update
# aptitude install git-core git-doc

2.2. Some further useful packages

# aptitude update
# aptitude install git-buildpackage git-cola git-cvs git-email git-gui \
                   git-load-dirs git-svn gitk gitosis gitpkg  \
                   gitweb jigit python-git qgit sigit stgit \
                   tig topgit

4. Working with Git

4.1. Commands

4.1.1. The most important commands

Create a new repository:

% git init

Clone an existing repository:

% git clone $URL

Add a file to the repository (-i for interactive):

% git add [-i] [$file(s)]

Remove a file from the repository:

% git rm $file

Check status:

% git status

List differences:

% git diff

To commit a change:

% git commit -m "<some comment>"

Commit all files via using the -a option:

% git commit -a -m "<some comment>"

Fetch updates:

% git pull [branch]

… which is just an abbreviation for:

% git fetch [branch] ; git merge [branch]

Push your changes:

% git push [remote-branch] [local-branch]

List all available branches:

% git branch -a

Check out specific branch:

% git checkout <commit object>

and switch back to master again:

% git checkout master

Merge one or more branches into current branch:

% git merge [branch]

Get a list of commits - the history:

% git log

View commit information:

% git show

Work with remote versions of the repository:

% git remote ...

Create a patch:

% git format-patch [-s -p origin/master]

Send patch via mail:

% git send-email <patch_file(s)>

Apply patch from mailbox file:

% git am ...

Tagging (using signing):

% git tag -s v0.42 -m 'release 0.42' # and don't forget: 'git push --tags'


% git config ....

Reset index and working directory to state of last commit:

% git reset --hard HEAD

Rework last commit:

% $EDITOR [<path/to/file>] # not necessary, depends on what you want to do
% git commit --amend [<path/to/file>]

Rewrite commit history (-i for interactive):

% git rebase [-i] master

4.1.2. Some further important commands

Commit (add) just parts of a file:

% git add --patch

Show a tree object:

% git ls-tree

View object:

% git cat-file


% git grep

Temporarily save changes without commiting:

% git stash

Provide archive of repository/tree:

% git archive

Check integrity of git repository:

% git fsck

Garbage collection for the repository:

% git gc

Remove dangling objects:

% git prune

Work with the reflog:

% git reflog

Display index:

% git ls-files --stage

Debugging using binary search:

% git bisect [start|good|bad|...]

Modify whole branches (like a massive rebase):

% git filter-branch

Show what revision and author last modified each line of a file:

% git blame ...

Delete a remote branch:

% git push origin :branch-to-delete

Delete stale branches that already been removed from the remote repository:

% git remote prune origin

4.2. Migrating from other VCS

| Git                      | Mercurial             | Subversion          |
| git status               | hg status             | svn status          |
| git pull                 | hg pull -u            | svn update          |
| git commit [-a]          | hg commit             | svn commit          |
| git init                 | hg create             | svnadmin create ... |
| git push --dry-run       | hg outgoing           | -                   |
| git buildpackage         | hg-buildpackage       | svn-buildpackage    |
| git add . &&             | hg addremove &&       | -                   |
| git commit -a            | hg commit             |                     |
| see section "Simple      | hg serve              | -                   |
| serving of repositories" |                       |                     |

4.3. Configuration

Either globally:

% git config --global user.name "Michael Prokop"
% git config --global user.email "mika@grml.org"

or per repository:

% git config user.name "Michael Prokop"
% git config user.email "mika@grml.org"

A git configuration file for inspiration is available online via gitconfig at grml-etc-core.

5. Debian specific stuff

5.1. Changelog handling

Commit changes to the Debian changelog of a package:

% debcommit [-C]

Generate the Debian changelog from git commit messages:

% git dch [--since 0.42]

5.2. Integrate upstream sources in Git

% pristine-tar ...

pristine-tar can regenerate a pristine upstream tarball using only a small binary delta file and a copy of the source which can be a revision control checkout.

5.3. Import Debian packages into a Git repository

% git import-dsc --pristine-tar $FILE.dsc

5.4. Import an upstream source into a git repository

% git import-orig /path/to/new-upstream.tar.gz -u 0.2

5.5. Build Debian packages from a Git repository

% git buildpackage

6. Tips and tricks for working

6.1. Solve merge conflicts

Example session:

% git checkout -b foo
% $EDITOR bla.txt
% git commit -a -m 'new feature: foo'
% git checkout master
% git merge foo
% git ls-files --stage
100644 c3382fdc386b6774e95e3a8bfdd083aa3004904b 0 bla.txt
100644 7abc07f0fcd2603606321dc7e3131453cf313da2 1 bla.txt
100644 7f16675fe783a8e4d1a8e672a8a4c1c25a1f61a0 2 bla.txt
% git cat-file blob $SHA1
% git cat-file commit $SHA1
% $EDITOR bla.txt
% git add bla.txt
% git commit -a -m 'merge branches'

6.2. Simple serving of repositories

Use the following alias in your ~/.gitconfig:

      serve = !git daemon --reuseaddr --verbose  --base-path=. -export-all ./.git

and when executing git serve in a repository someone can access it through git://$IPADDRESS/, like:

git ls-remote git://


git clone git:// reposname

where the IP address corresponds with the system where git serve has been executed of course.

Note Make sure to use a "/" at the end of the URL when using the git protocol ("git://")!

6.3. Use graphviz for display

Configure ~/.gitconfig:

      graphviz = "!f() { echo 'digraph git {' ; git log --pretty='format: %h -> { %p }' \"$@\" | sed 's/[0-9a-f]\\+/\"&\"/g' ; echo '}'; }; %f"

and then run something like:

git graphviz HEAD^^..HEAD | dotty /dev/stdin
git graphviz --first-parent master | dotty /dev/stdin

Tip taken from http://git.or.cz/gitwiki/Aliases.

6.4. Force linear development

Use the .git/hooks/update script to allow only fast-forward-updates so only pushes of people using current HEAD are possible.

6.5. Move current development into a dedicated branch

Very useful if you forgot to checkout a separate branch for working, so move the into a branch as if you were developing it there since the very beginning:

% git commit ... # to make sure you don't lose anything
% git branch topic/wip
% git reset --hard '@{2 hours ago}'
% git checkout topic/wip

6.6. Bidirectional operation between subversion and git

Use git svn, like:

% git svn clone http://... foo
% cd foo
% git commit ...
% git svn rebase # like svn up
% git svn dcommit # push changes to SVN repository
% git svn show-ignore >> .git/info/exclude # import svn:ignore properties

Further information available for example in "git-svn in 30 minutes", "Git - SVN Crash Course" and "An introduction to git-svn for Subversion/SVK users and deserters".

6.7. Manage several repositories at once

mr is a Multiple Repository management tool which can checkout, update, or perform other actions on a set of repositories as if they were one combined respository. It supports any combination of subversion, git, cvs, mecurial, bzr, and darcs repositories, and support for other revision control systems can easily be added.

6.8. Automatic testing of recent version

gitbuilder tests the most recent versions of all tags and branches in your project.

6.9. Graphical interfaces

6.10. Patch management

7. Server setup

7.1. Activate backports and install software

cat >> /etc/apt/sources.list << EOF
deb http://www.backports.org/debian etch-backports main contrib non-free
aptitude update
aptitute install debian-backports-keyring gpm asciidoc
cat > /etc/apt/preferences << EOF
Package: git-core
Pin: release a=etch-backports
Pin-Priority: 999
Package: git-buildpackage
Pin: release a=etch-backports
Pin-Priority: 999
Package: gitosis
Pin: release a=etch-backports
Pin-Priority: 999
Package: gitweb
Pin: release a=etch-backports
Pin-Priority: 999
Package: devscripts
Pin: release a=etch-backports
Pin-Priority: 999

Direct installation might fail due to problem in python-setuptools (version 0.6c8-4~bpo40+1), therefor manual intervention through dpkg in between:

aptitude install git-core git-buildpackage gitosis devscripts gitweb
dpkg -i /var/cache/apt/archives/python-setuptools_0.6c8-4\~bpo40+1_all.deb
aptitude install git-core git-buildpackage gitosis devscripts gitweb

7.2. Setup of apache2

See also /usr/share/doc/git-core/README.Debian

aptitude install apache2
$EDITOR /etc/apache2/sites-available/default
<VirtualHost *:80>
   ServerName git.grml.org
   ServerAdmin git@grml.org
ErrorLog /var/log/apache2/git_error.log
CustomLog /var/log/apache2/git_access.log combined
ServerSignature On
HeaderName HEADER
# bogus but safe DocumentRoot
DocumentRoot /home/git/repositories
   Alias /gitweb.css /usr/share/gitweb/gitweb.css
   Alias /git-favicon.png /usr/share/gitweb/git-favicon.png
   Alias /git-logo.png /usr/share/gitweb/git-logo.png
   Alias /icons /usr/share/apache2/icons/
   Alias /git /var/cache/git
   ScriptAlias / /usr/lib/cgi-bin/gitweb.cgi
   RedirectMatch permanent "^/~(.*)$" "http://git.grml.org/~$1"
Note If you use lighttpd instead of apache2 check out /usr/share/doc/gitosis/examples/lighttpd-gitweb.conf and 20-git.conf.

7.3. Configure gitweb

Adjust configuration file /etc/gitweb.conf:

$EDITOR /etc/gitweb.conf
$projectroot = "/home/git/repositories";
$projects_list = "/home/git/gitosis/projects.list";
@git_base_url_list = "git://git.grml.org";
# to use your own header text on the startpage:
# $home_text = "/home/git/gitweb-header.txt";
# By default, gitweb will happily let people browse any repository
# they guess the name of. This may or may not be what you wanted.  I
# choose to allow gitweb to show only repositories that git-daemon
# is already sharing anonymously.
$export_ok = "git-daemon-export-ok";

7.4. User setup

Disable user gitosis and add user git instead (to avoid any possible damages through Debian packages):

usermod --shell /bin/false gitosis
addgroup git
adduser --system --home /home/git --shell /bin/sh --disabled-password --gecos 'git repository hosting' --ingroup git git
sudo -H -u git gitosis-init < /home/mika/.ssh/id_rsa.pub
chgrp -R www-data /home/git
chmod 2755 /home/git/repositories

7.5. Configuration of gitosis-admin

Clone gitosis-admin to client via executing the following command line on the client with the id_rsa.pub key:

git clone ssh://git@git.grml.org/gitosis-admin.git

Edit gitosis.conf of gitosis-admin repository:

# Permissions:
[group gitosis-admin]
writable = gitosis-admin
members = mika@tweety
[group coreteam]
members = mika@tweety gebi
# gebi = Michael Gebetsroither
writable = grml-git-tools grml-git-doc
# Testrepos:
[group mika]
writable = testrepo
members = mika@tweety
# Repositories:
[repo grml-git-doc]
description = Documentation of git at grml
owner = Michael Prokop <mika@grml.org>
[repo grml-git-tools]
description = Useful addons for work with git
owner = Michael Prokop <mika@grml.org>

And push changes:

git commit -a -m 'add testrepo with user mika@tweety'
git push

Create a test repository on the client(!) and push it to the server:

cd /tmp
mkdir testrepo
cd testrepo
git init
git remote add origin ssh://git@git.grml.org/testrepo.git
echo testfile > testfile
git add testfile
git commit -a -m 'initial checkin'
git push origin master

7.6. Setup of git-daemon

git-daemon provides repositories via git protocol. You can either use git-daemon via runit installing the Debian package git-daemon-run or via running git-daemon standalone. For the later option run:

cd /etc/init.d
wget -O git-daemon 'http://git.grml.org/?p=grml-git-doc.git;a=blob_plain;f=git-daemon;hb=HEAD'
chmod +x ./git-daemon
/etc/init.d/git-daemon start

8. Working with the server setup

Members with ssh permissions can clone the repository running:

% git clone ssh://git@git.grml.org/testrepo

Anonymous check out using the git protocol via:

% git clone git://git.grml.org/testrepo

Do not add a trailing slash (as in ssh://git.grml.org/grml-repo.git/) to the remote repository's URL.

9. Resources

9.1. Online stuff

9.2. Books

9.3. Videos / Talks

9.4. PDFs/ Slides

9.5. Git-Hosting

Notice: please consider use with care.

9.6. Limitations of git

10. TODO

11. About this document

Main author: