diff --git a/Git/Utils.hs b/Git/Utils.hs
--- a/Git/Utils.hs
+++ b/Git/Utils.hs
@@ -19,18 +19,39 @@
 import           Data.Function
 import           Data.HashSet (HashSet)
 import qualified Data.HashSet as HashSet
+import           Data.Hex
 import           Data.List
+import           Data.Maybe
 import           Data.Monoid
 import           Data.Tagged
 import           Data.Text (Text)
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
 import           Data.Traversable hiding (mapM, forM, sequence)
 import           Filesystem (removeTree, isDirectory)
 import           Filesystem.Path.CurrentOS hiding (null, concat)
 import           Git
 import           Prelude hiding (FilePath)
 
+data OidBytestring = OidBytestring { getOidBS :: ByteString }
+                   deriving (Eq, Ord, Show)
+
+instance IsOid OidBytestring where
+    renderOid (OidBytestring x) = T.toLower (T.decodeUtf8 (hex x))
+
+parseOidBytestring :: Monad m => Text -> m OidBytestring
+parseOidBytestring x = OidBytestring `liftM` unhex (T.encodeUtf8 x)
+
+data OidTextL = OidTextL { getOidTL :: TL.Text }
+              deriving (Eq, Ord, Show)
+
+instance IsOid OidTextL where
+    renderOid (OidTextL x) = TL.toStrict x
+
+parseOidTextL :: Monad m => Text -> m OidTextL
+parseOidTextL = return . OidTextL . TL.fromStrict
+
 treeOid :: Repository m => Tree m -> m Text
 treeOid t = renderObjOid <$> writeTree t
 
@@ -68,9 +89,15 @@
 blobToByteString :: Repository m => Blob m -> m ByteString
 blobToByteString (Blob _ contents) = blobContentsToByteString contents
 
+splitPath :: FilePath -> [Text]
+splitPath path = T.splitOn "/" text
+  where text = case toText path of
+                 Left x  -> error $ "Invalid path: " ++ T.unpack x
+                 Right y -> y
+
 treeBlobEntries :: Repository m => Tree m -> m [(FilePath,TreeEntry m)]
 treeBlobEntries tree =
-    mconcat <$> traverseEntries tree go
+    mconcat <$> traverseEntries go tree
   where
     go fp e@(BlobEntry _ PlainBlob) = return [(fp,e)]
     go fp e@(BlobEntry _ ExecutableBlob) = return [(fp,e)]
@@ -81,7 +108,7 @@
                 -> FilePath
                 -> m (Maybe (TreeEntry m))
 commitTreeEntry c path =
-    flip lookupEntry path =<< resolveTreeRef (commitTree c)
+    flip getTreeEntry path =<< resolveTreeRef (commitTree c)
 
 copyOid :: (Repository m, Repository (t m), MonadTrans t)
         => Oid m -> t m (Oid (t m))
@@ -128,11 +155,10 @@
     oid2 <- parseOid (renderOid oid)
     if HashSet.member sha needed
         then do
-        tree    <- lift $ resolveTreeRef tr
-        entries <- lift $ traverseEntries tree (curry return)
-        tree2   <- newTree
-        needed' <- foldM (doCopyTreeEntry tree2) needed entries
-        toid    <- writeTree tree2
+        tree             <- lift $ resolveTreeRef tr
+        entries          <- lift $ traverseEntries (curry return) tree
+        (needed', tree2) <- withNewTree $ foldM doCopyTreeEntry needed entries
+        toid             <- writeTree tree2
 
         let tref = ByOid toid
             x    = HashSet.delete sha needed'
@@ -140,10 +166,13 @@
 
         else return (ByOid (Tagged oid2), needed)
   where
-    doCopyTreeEntry _ needed' (_,TreeEntry {}) = return needed'
-    doCopyTreeEntry tree2 needed' (fp,ent) = do
-        (ent2,needed'') <- copyTreeEntry ent needed'
-        putTreeEntry tree2 fp ent2
+    doCopyTreeEntry :: (Repository m, Repository (t m), MonadTrans t)
+                    => HashSet Text -> (FilePath, TreeEntry m)
+                    -> TreeT (t m) (HashSet Text)
+    doCopyTreeEntry needed' (_,TreeEntry {}) = return needed'
+    doCopyTreeEntry needed' (fp,ent) = do
+        (ent2,needed'') <- lift $ copyTreeEntry ent needed'
+        putEntry fp ent2
         return needed''
 
 copyCommit :: (Repository m, Repository (t m), MonadTrans t)
@@ -187,7 +216,7 @@
     fmap concat . forM objs $ \obj -> case obj of
         TreeObj ref -> do
             tr       <- resolveTreeRef ref
-            subobjss <- traverseEntries tr $ \_ ent ->
+            subobjss <- flip traverseEntries tr $ \_ ent ->
                 return $ case ent of
                     Git.BlobEntry oid _ -> [Git.BlobObj (Git.ByOid oid)]
                     Git.TreeEntry tr'   -> [Git.TreeObj tr']
diff --git a/gitlib-utils.cabal b/gitlib-utils.cabal
--- a/gitlib-utils.cabal
+++ b/gitlib-utils.cabal
@@ -1,5 +1,5 @@
 Name:                gitlib-utils
-Version:             1.0.1
+Version:             1.1.0
 Synopsis:            Generic utility functions for working with Git repositories
 License-file:        LICENSE
 License:             MIT
@@ -33,11 +33,12 @@
     ghc-options: -Wall
     build-depends:
           base                 >= 3 && < 5
-        , gitlib
+        , gitlib               >= 1.1.0
         , bytestring           >= 0.9.2.1
         , conduit              >= 0.5.5
         , data-default         >= 0.5.1
         , failure              >= 0.2.0.1
+        , hex                  >= 0.1.2
         , lifted-base          >= 0.2.0.2
         , system-fileio        >= 0.3.11
         , system-filepath      >= 0.4.7
