diff --git a/Git/Sample.hs b/Git/Sample.hs
new file mode 100644
--- /dev/null
+++ b/Git/Sample.hs
@@ -0,0 +1,132 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+{-# OPTIONS_GHC -fno-warn-name-shadowing
+                -fno-warn-unused-binds
+                -fno-warn-orphans #-}
+
+module Git.Sample
+       ( SampleRepository(..), Repository(..)
+       , Git.Oid(..), BlobOid(), TreeOid(), CommitOid()
+       , Tree(), Commit()
+       , TreeRef(), CommitRef(), Reference()
+       , sampleFactory
+       , sampleGet
+       ) where
+
+import           Control.Applicative
+import           Control.Monad.IO.Class
+import           Control.Monad.Trans.Class
+import           Control.Monad.Trans.Reader
+import           Filesystem.Path.CurrentOS as F
+import           Prelude hiding (FilePath)
+import qualified Git
+
+data Void
+
+instance Git.MonadGit m => Git.Repository (SampleRepository m) where
+    data Oid (SampleRepository m)      = Oid Void
+    data TreeData (SampleRepository m) = Void
+    data Options (SampleRepository m)  = Options
+
+    facts = return Git.RepositoryFacts
+        { Git.hasSymbolicReferences = True }
+
+    parseOid         = undefined
+    renderOid        = undefined
+    lookupRef        = undefined
+    createRef        = undefined
+    updateRef        = undefined
+    deleteRef        = undefined
+    resolveRef       = undefined
+    allRefNames      = undefined
+    lookupCommit     = undefined
+    lookupTree       = undefined
+    lookupBlob       = undefined
+    lookupTag        = undefined
+    lookupObject     = undefined
+    existsObject     = undefined
+    pushCommit       = undefined
+    traverseCommits  = undefined
+    missingObjects   = undefined
+    traverseObjects  = undefined
+    newTree          = undefined
+    hashContents     = undefined
+    createBlob       = undefined
+    createCommit     = undefined
+    createTag        = undefined
+    deleteRepository = undefined
+    remoteFetch      = undefined
+
+instance Show (Git.Oid (SampleRepository m)) where
+    show (Oid _coid) = undefined
+
+instance Ord (Git.Oid (SampleRepository m)) where
+    Oid _coid1 `compare` Oid _coid2 = undefined
+
+instance Eq (Git.Oid (SampleRepository m)) where
+    oid1 == oid2 = oid1 `compare` oid2 == EQ
+
+-- type TreeEntry m = Git.TreeEntry (SampleRepository m)
+
+data Repository = Repository Void
+
+instance Eq Repository where
+  _x == _y = undefined
+
+instance Show Repository where
+  show _x = undefined
+
+newtype SampleRepository m a = SampleRepository
+    { sampleRepositoryReaderT :: ReaderT Repository m a }
+    deriving (Functor, Applicative, Monad, MonadIO, MonadTrans)
+
+type BlobOid m   = Git.BlobOid (SampleRepository m)
+type TreeOid m   = Git.TreeOid (SampleRepository m)
+type CommitOid m = Git.CommitOid (SampleRepository m)
+--type TagOid m    = Git.TagOid (SampleRepository m)
+
+type Tree m      = Git.Tree (SampleRepository m)
+type Commit m    = Git.Commit (SampleRepository m)
+
+type TreeRef m   = Git.TreeRef (SampleRepository m)
+type CommitRef m = Git.CommitRef (SampleRepository m)
+
+type Reference m = Git.Reference (SampleRepository m) (Commit m)
+
+sampleGet :: Monad m => SampleRepository m Repository
+sampleGet = SampleRepository ask
+
+sampleFactory :: Git.MonadGit m
+              => Git.RepositoryFactory SampleRepository m Repository
+sampleFactory = Git.RepositoryFactory
+    { Git.openRepository  = openSampleRepository
+    , Git.runRepository   = runSampleRepository
+    , Git.closeRepository = closeSampleRepository
+    , Git.getRepository   = sampleGet
+    , Git.defaultOptions  = defaultSampleOptions
+    , Git.startupBackend  = return ()
+    , Git.shutdownBackend = return ()
+    }
+
+openSampleRepository :: Git.MonadGit m => Git.RepositoryOptions -> m Repository
+openSampleRepository _opts = undefined
+
+runSampleRepository :: Git.MonadGit m
+                    => Repository -> SampleRepository m a -> m a
+runSampleRepository repo action =
+    runReaderT (sampleRepositoryReaderT action) repo
+
+closeSampleRepository :: Git.MonadGit m => Repository -> m ()
+closeSampleRepository = const (return ())
+
+defaultSampleOptions :: Git.RepositoryOptions
+defaultSampleOptions = Git.RepositoryOptions F.empty False False
+
+-- Sample.hs
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+opyright (c) 2012 John Wiegley
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/gitlib-sample.cabal b/gitlib-sample.cabal
new file mode 100644
--- /dev/null
+++ b/gitlib-sample.cabal
@@ -0,0 +1,43 @@
+Name:                gitlib-sample
+Version:             1.0.1
+Synopsis:            Sample backend for gitlib showing the basic structure for any backend.
+License-file:        LICENSE
+License:             MIT
+Author:              John Wiegley
+Maintainer:          johnw@fpcomplete.com
+Build-Type:          Simple
+Cabal-Version:       >=1.10
+Category:            FFI
+Description:
+  Sample backend for @gitlib@.
+
+Source-repository head
+  type: git
+  location: git://github.com/fpco/gitlib.git
+
+-- Test-suite smoke
+--     Default-language: Haskell98
+--     Type: exitcode-stdio-1.0
+--     Main-is: Smoke.hs
+--     Hs-source-dirs: test
+--     Build-depends: 
+--           base >=3
+--         , gitlib
+--         , gitlib-test
+--         , gitlib-sample
+--         , HUnit              >= 1.2.5
+--         , hspec              >= 1.4.4
+--         , hspec-expectations >= 0.3
+
+Library
+    default-language:   Haskell98
+    ghc-options: -Wall
+    build-depends:
+          base                 >= 3 && < 5
+        , gitlib
+        , failure              >= 0.2.0.1
+        , system-filepath      >= 0.4.7
+        , tagged               >= 0.2.3.1
+        , transformers         >= 0.3.0.0
+    exposed-modules:
+        Git.Sample
