diff --git a/Data/Git/Commit.hs b/Data/Git/Commit.hs
--- a/Data/Git/Commit.hs
+++ b/Data/Git/Commit.hs
@@ -13,6 +13,8 @@
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as E
 import qualified Data.Text.ICU.Convert as U
+import qualified Foreign.Concurrent as FC
+import qualified Foreign.ForeignPtr.Unsafe as FU
 import           Foreign.Marshal.Array
 import qualified Prelude
 
@@ -25,8 +27,7 @@
                      , _commitEncoding  :: Prelude.String
                      , _commitTree      :: ObjRef Tree
                      , _commitParents   :: [ObjRef Commit]
-                     -- , _commitObj       :: ObjPtr C'git_commit
-                     }
+                     , _commitObj       :: ObjPtr C'git_commit }
 
 makeClassy ''Commit
 
@@ -61,7 +62,8 @@
          , _commitTree      = ObjRef (createTree repo)
          , _commitParents   = []
          , _commitLog       = T.empty
-         , _commitEncoding  = "" }
+         , _commitEncoding  = ""
+         , _commitObj       = Nothing }
 
 lookupCommit :: Oid -> Repository -> IO (Maybe Commit)
 lookupCommit oid repo =
@@ -82,10 +84,11 @@
         toid  <- c'git_commit_tree_oid c  >>= wrapOidPtr
 
         pn    <- c'git_commit_parentcount c
-        poids <- traverse wrapOidPtr =<<
-                (sequence $
-                 zipWith ($) (replicate (fromIntegral (toInteger pn))
-                                        (c'git_commit_parent_oid c)) [0..pn])
+        poids <- traverse wrapOidPtr
+                =<< sequence
+                      (zipWith ($) (replicate (fromIntegral (toInteger pn))
+                                              (c'git_commit_parent_oid c))
+                                   [0..pn])
 
         return Commit { _commitInfo      = newBase repo (Stored coid) (Just obj)
                       , _commitAuthor    = auth
@@ -93,7 +96,8 @@
                       , _commitTree      = toid
                       , _commitParents   = poids
                       , _commitLog       = U.toUnicode conv msg
-                      , _commitEncoding  = encs }
+                      , _commitEncoding  = encs
+                      , _commitObj       = Just $ unsafeCoerce obj }
 
 withGitCommit :: Updatable b
               => ObjRef Commit -> b -> (Ptr C'git_commit -> IO a) -> IO a
@@ -126,15 +130,15 @@
               withEncStr (c^.commitEncoding) $ \message_encoding ->
                 withGitTree (c^.commitTree) c $ \commit_tree -> do
                   parentPtrs <- getCommitParentPtrs c
-                  flip finally (freeCommits parentPtrs) $ do
-                    parents <- newArray parentPtrs
-                    r <- c'git_commit_create coid' repoPtr
-                         update_ref author committer
-                         message_encoding message commit_tree
-                         (fromIntegral (length (c^.commitParents)))
-                         parents
-                    when (r < 0) $ throwIO CommitCreateFailed
-                    return coid
+                  parents    <- newArray $
+                               map FU.unsafeForeignPtrToPtr parentPtrs
+                  r <- c'git_commit_create coid' repoPtr
+                        update_ref author committer
+                        message_encoding message commit_tree
+                        (fromIntegral (length (c^.commitParents)))
+                        parents
+                  when (r < 0) $ throwIO CommitCreateFailed
+                  return coid
 
   return (commitInfo.gitId .~ Stored (COid coid) $ c, COid coid)
 
@@ -152,8 +156,6 @@
       then flip ($) nullPtr
       else withCString enc
 
-    freeCommits = traverse c'git_commit_free
-
 getCommitParents :: Commit -> IO [Commit]
 getCommitParents c =
   traverse (\p -> do parent <- loadObject p c
@@ -162,18 +164,37 @@
                        Just p' -> return p')
            (c^.commitParents)
 
-getCommitParentPtrs :: Commit -> IO [Ptr C'git_commit]
+getCommitParentPtrs :: Commit -> IO [ForeignPtr C'git_commit]
 getCommitParentPtrs c =
   withForeignPtr (repositoryPtr (objectRepo c)) $ \repoPtr ->
-    for (c^.commitParents) $ \p -> do
-      Oid (COid oid) <- case p of
-        IdRef coid -> return $ Oid coid
-        ObjRef x   -> objectId x
+    for (c^.commitParents) $ \p ->
+      case p of
+        ObjRef (Commit { _commitObj = Just obj }) -> return obj
+        _ -> do
+          Oid (COid oid) <-
+            case p of
+              IdRef coid -> return $ Oid coid
+              ObjRef x   -> objectId x
 
-      withForeignPtr oid $ \commit_id ->
-        alloca $ \ptr -> do
-          r <- c'git_commit_lookup ptr repoPtr commit_id
-          when (r < 0) $ throwIO CommitLookupFailed
-          peek ptr
+          withForeignPtr oid $ \commit_id ->
+            alloca $ \ptr -> do
+              r <- c'git_commit_lookup ptr repoPtr commit_id
+              when (r < 0) $ throwIO CommitLookupFailed
+              ptr' <- peek ptr
+              FC.newForeignPtr ptr' (c'git_commit_free ptr')
+
+doUpdateCommit :: [Text] -> TreeEntry -> Commit -> IO Commit
+doUpdateCommit xs item c = do
+  t <- loadObject (c^.commitTree) c
+  case t of
+    Nothing -> error "Failed to load tree for commit"
+    Just t' -> do
+      tr <- doModifyTree xs (const (Right (Just item))) True t'
+      case tr of
+        Right tr' -> return $ commitTree .~ ObjRef tr' $ c
+        _ -> undefined
+
+updateCommit :: FilePath -> TreeEntry -> Commit -> IO Commit
+updateCommit = doUpdateCommit . splitPath
 
 -- Commit.hs
diff --git a/Data/Git/Reference.hs b/Data/Git/Reference.hs
--- a/Data/Git/Reference.hs
+++ b/Data/Git/Reference.hs
@@ -9,7 +9,8 @@
        , createRef
        , lookupRef
        , lookupId
-       , writeRef )
+       , writeRef
+       , writeRef_ )
        where
 
 import           Bindings.Libgit2
@@ -45,9 +46,9 @@
 lookupRef :: Text -> Repository -> IO (Maybe Reference)
 lookupRef name repo = alloca $ \ptr -> do
   r <- withForeignPtr (repositoryPtr repo) $ \repoPtr ->
-    withCStringable name $ \namePtr ->
-      c'git_reference_lookup ptr repoPtr namePtr
-  if (r < 0)
+        withCStringable name $ \namePtr ->
+          c'git_reference_lookup ptr repoPtr namePtr
+  if r < 0
     then return Nothing
     else do
     ref  <- peek ptr
@@ -81,6 +82,9 @@
 
   where
     repo = fromMaybe (error "Repository invalid") (ref^.refRepo.repoObj)
+
+writeRef_ :: Reference -> IO ()
+writeRef_ = void . writeRef
 
 -- int git_reference_name_to_oid(git_oid *out, git_repository *repo,
 --   const char *name)
diff --git a/gitlib.cabal b/gitlib.cabal
--- a/gitlib.cabal
+++ b/gitlib.cabal
@@ -1,5 +1,5 @@
 Name:                gitlib
-Version:             0.3.0
+Version:             0.4.0
 Synopsis:            Higher-level types for working with hlibgit2
 Description:         Higher-level types for working with hlibgit2
 License-file:        LICENSE
