diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cedf4fae5a3ae9afe9e68be73b38a395f5b9dde6
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,15 @@
+language: perl
+before_install:
+  - cpanm Shell::Command
+  - cpanm Test::Most
+  - apt-get moo
+install:
+  - sudo apt-get install cowsay git ruby-ronn
+script:
+  - make test
+after_script:
+  - make moo
+notifications:
+  email:
+    on_success: change
+    on_failure: always
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index d7a3394767a47d8d5d865a9ed2fb422797d7f438..cf2861986588825c01ad5b5a749c4847e3eee7d1 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -11,6 +11,7 @@ Jeff Fein-Worton <jeff@fein-worton.com>
 Thomas Ferris Nicolaisen <tfnico@gmail.com>
 martin f. krafft <madduck@madduck.net>
 Alessandro Ghedini <alessandro@ghedini.me>
+Dennis Gilmore <dennis@ausil.us>
 Thorsten Glaser <tg@mirbsd.org>
 G.raud <graud@gmx.com>
 Mikhail Gusarov <dottedmag@dottedmag.net>
@@ -33,6 +34,7 @@ Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
 Dato Simó <dato@net.com.org.es>
 Alexander Skurikhin <a.skurihin@gmail.com>
 Jonathan Sternberg <jonathansternberg@gmail.com>
+Mathias Svensson <freaken@freaken.dk>
 Frank Terbeck <ft@bewatermyfriend.org>
 mirabilos <tg@debian.org>
 Aaron VonderHaar <gruen0aermel@gmail.com>
diff --git a/Makefile b/Makefile
index ed0aebc51867b8dc6250d0aa45cc5d2306da5c65..b15779de0526bbf8190fa0cfd9cd5b628bb1612a 100644
--- a/Makefile
+++ b/Makefile
@@ -40,11 +40,12 @@ uninstall:
 purge: uninstall
 	rmdir -p --ignore-fail-on-non-empty $(DESTDIR)$(PREFIX)/bin/
 	rmdir -p --ignore-fail-on-non-empty $(DESTDIR)$(PREFIX)/share/man/man1/
-	rmdir -p --ignore-fail-on-non-empty $(DESTDIR)$(DOCDIR_PREFIX)
+	rmdir -p --ignore-fail-on-non-empty $(DESTDIR)$(DOCDIR)
 	rmdir -p --ignore-fail-on-non-empty $(DESTDIR)$(ZSHDIR)
 
 test:
-	@if which git > /dev/null ; then :; else echo "'git' not found, exiting..."; exit 1; fi
+	@if which git   > /dev/null; then :    ; else echo "'git' not found, exiting..."         ; exit 1; fi
+	@if which prove > /dev/null; then prove; else echo "'prove' not found; not running tests";         fi
 
 moo:
-	@ which cowsay >/dev/null 2>&1 && cowsay "I hope you're happy now..."
+	@which cowsay >/dev/null 2>&1 && cowsay "I hope you're happy now..."
diff --git a/README.md b/README.md
index 763b7c462d39d0e496d11cc22121f5a96d155c02..f885b4a3cb1ad8097e451be32ac5582accea72df 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
 vcsh - Version Control System for $HOME - multiple Git repositories in $HOME
 
+[![Build Status](https://travis-ci.org/RichiH/vcsh.svg?branch=master)](https://travis-ci.org/RichiH/vcsh)
+
 
 # Index
 
diff --git a/doc/INSTALL.md b/doc/INSTALL.md
index 29c9889194866fd66a256374e406a799cdd2dd7b..65fc5f3b48adc256f6143d72494e23faae1d3367 100644
--- a/doc/INSTALL.md
+++ b/doc/INSTALL.md
@@ -14,6 +14,12 @@ There are no other dependencies other than `git`, `ronn` and a POSIX shell.
 
 	sudo make install
 
+## Installing without root privileges ##
+
+	make install DESTDIR=/home/myuser/local
+
+or simply copy the shell script into any place you like, e.g. `~/bin`
+
 
 # Uninstalling #
 
diff --git a/doc/vcsh.1.ronn b/doc/vcsh.1.ronn
index 1d432c3a0f6001753d601bd673366bff921af42c..cd73ca8b04a8d2cb0d365c552d26965d6ab09983 100644
--- a/doc/vcsh.1.ronn
+++ b/doc/vcsh.1.ronn
@@ -17,7 +17,7 @@ vcsh(1) - Version Control System for $HOME - multiple Git repositories in $HOME
 
 `vcsh` list
 
-`vcsh` list-tracked [<rpoe>]
+`vcsh` list-tracked [<repo>]
 
 `vcsh` list-untracked [<-r>] [<repo>]
 
diff --git a/t/000-tear-env.t b/t/000-tear-env.t
new file mode 100644
index 0000000000000000000000000000000000000000..6cb384f15bc061378cc8f78e4ec5d6caa74c2aa1
--- /dev/null
+++ b/t/000-tear-env.t
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Shell::Command;
+use Test::Most;
+
+chdir 't' or die $!;
+
+if (!-d 'etc') {
+	plan skip_all => 'No need to tear down previous env.';
+}
+
+ok rm_rf 'etc';
+
+done_testing;
diff --git a/t/001-setup-env.t b/t/001-setup-env.t
new file mode 100644
index 0000000000000000000000000000000000000000..fb59f058e3f04826ced8230617f2e6e818f18ae3
--- /dev/null
+++ b/t/001-setup-env.t
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::Most;
+
+system ("mkdir -p t/etc");
+ok !$?;
+
+system ("mkdir -p t/etc/.vcsh_home");
+ok !$?;
+
+chdir 't/etc/' or die $!;
+
+system ("ln -s '../../vcsh'");
+ok !$?;
+
+done_testing;
diff --git a/t/100-init.t b/t/100-init.t
new file mode 100644
index 0000000000000000000000000000000000000000..f2b3a05155b66cfeb7c124d79cf97168b5cb7043
--- /dev/null
+++ b/t/100-init.t
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Cwd 'abs_path';
+use Test::Most;
+
+chdir 't/etc/' or die $!;
+
+$ENV{'HOME'} = abs_path ('.vcsh_home');
+
+my $output = `./vcsh status`;
+
+ok $output eq "", 'No repos set up yet.';
+
+$output = `./vcsh init test1`;
+
+ok $output eq "Initialized empty shared Git repository in " . $ENV{'HOME'} . "/.config/vcsh/repo.d/test1.git/\n";
+
+$output = `./vcsh status`;
+
+ok $output eq "test1:\n\n", 'Our new repo is there';
+
+chdir $ENV{"HOME"} . '/.config/vcsh/repo.d/test1.git/' or die $!;
+
+ok -f 'HEAD';
+ok -d 'branches';
+ok -f 'config';
+ok -f 'description';
+ok -d 'hooks';
+ok -d 'info';
+ok -d 'objects';
+ok -d 'refs';
+
+ok -f 'hooks/applypatch-msg.sample';
+ok -f 'hooks/commit-msg.sample';
+ok -f 'hooks/post-update.sample';
+ok -f 'hooks/pre-applypatch.sample';
+ok -f 'hooks/pre-commit.sample';
+ok -f 'hooks/pre-push.sample';
+ok -f 'hooks/pre-rebase.sample';
+ok -f 'hooks/prepare-commit-msg.sample';
+ok -f 'hooks/update.sample';
+
+ok -f 'info/exclude';
+
+ok -d 'objects/info';
+ok -d 'objects/pack';
+
+ok -d 'refs/heads';
+ok -d 'refs/tags';
+
+done_testing;
diff --git a/t/300-add.t b/t/300-add.t
new file mode 100644
index 0000000000000000000000000000000000000000..24d9a8ae8742f9ae37204fcadccbe430bbbeb601
--- /dev/null
+++ b/t/300-add.t
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Cwd 'abs_path';
+
+use Shell::Command;
+use Test::Most;
+
+chdir 't/etc/' or die $!;
+
+$ENV{'HOME'} = abs_path ('.vcsh_home');
+
+chdir '.vcsh_home' or die $!;
+
+eval {
+	touch 'a';
+};
+
+die $@ if $@;
+
+system (".././vcsh test1 add 'a'");
+
+my $output = `.././vcsh status`;
+
+ok $output eq "test1:
+A  a
+
+", 'Adding a file works';
+
+done_testing;
+
diff --git a/t/950-delete.t b/t/950-delete.t
new file mode 100644
index 0000000000000000000000000000000000000000..cd078714ad0c3c7396bc88c89966dd32f7ee0ed7
--- /dev/null
+++ b/t/950-delete.t
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Cwd 'abs_path';
+use Test::Most;
+
+chdir 't/etc/' or die $!;
+
+$ENV{'HOME'} = abs_path ('.vcsh_home');
+
+system ("echo 'Yes, do as I say' | ./vcsh delete test1");
+
+my $output = `./vcsh status`;
+
+ok $output eq "", 'No repos set up anymore.';
+
+done_testing;
diff --git a/t/999-tear-env.t b/t/999-tear-env.t
new file mode 100644
index 0000000000000000000000000000000000000000..afe261a8a5ba3f10ec45a2f6b15d711743132ec9
--- /dev/null
+++ b/t/999-tear-env.t
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Shell::Command;
+use Test::Most;
+
+chdir 't' or die $!;
+
+if (!-d 'etc') {
+	plan skip_all => 'No need to tear previous env.';
+}
+
+ok rm_rf 'etc';
+
+done_testing;
diff --git a/tools/hooks/pre-commit b/tools/hooks/pre-commit
new file mode 100755
index 0000000000000000000000000000000000000000..ddb0550d640a1b4bd901877b090df5278df7e729
--- /dev/null
+++ b/tools/hooks/pre-commit
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# Unfortunately, Git decided to set those two during pre-commit
+unset GIT_DIR
+unset GIT_INDEX_FILE
+
+prove
diff --git a/vcsh b/vcsh
index 0f2c5af7373af05fa9a0510ff6173df44ac31ab7..51f2d2125a0bd52e09681e5d80f40ea0488e5efc 100755
--- a/vcsh
+++ b/vcsh
@@ -312,7 +312,7 @@ list_untracked_helper() {
 		cp $temp_file_others $temp_file_untracked || fatal 'Could not copy temp file'
 	fi
 	cp $temp_file_untracked $temp_file_untracked_copy || fatal 'Could not copy temp file'
-	comm -12 --nocheck-order $temp_file_others $temp_file_untracked_copy > $temp_file_untracked
+	comm -12 $temp_file_others $temp_file_untracked_copy > $temp_file_untracked
 }
 
 pull() {