diff --git a/Data/Git/Diff.hs b/Data/Git/Diff.hs
index ad81d8e1b88c2fdccff92f6e5218dc1de32a6709..289922a3b06d13e00fad646d82bd6bed6997b74e 100644
--- a/Data/Git/Diff.hs
+++ b/Data/Git/Diff.hs
@@ -36,7 +36,8 @@ import Data.Git.Storage.Object
 import Data.ByteString.Lazy.Char8 as L
 
 import Data.Typeable
-import Data.Algorithm.Patience as AP (Item(..), diff)
+import Data.Git.Diff.Patience (Item(..), diff)
+
 
 -- | represents a blob's content (i.e., the content of a file at a given
 -- reference).
@@ -257,22 +258,21 @@ diffGetContext context list =
     let (_, _, filteredDiff) = Prelude.foldr filterContext (0, AccuBottom, []) list
         theList = removeTrailingBoth filteredDiff
     in case Prelude.head theList of
-        (NormalLine (Both l1 _)) -> if (lineNumber l1) > 1 then Separator:theList
-                                                           else theList
+        (NormalLine (Both l _)) -> if lineNumber l > 1 then Separator:theList else theList
         _ -> theList
     where -- only keep 'context'. The file is annalyzed from the bottom to the top.
           -- The accumulator here is a tuple3 with (the line counter, the
           -- direction and the list of elements)
           filterContext :: (Item TextLine) -> (Int, GitAccu, [FilteredDiff]) -> (Int, GitAccu, [FilteredDiff])
-          filterContext (Both l1 l2) (c, AccuBottom, acc) =
-              if c < context then (c+1, AccuBottom, (NormalLine (Both l1 l2)):acc)
-                             else (c  , AccuBottom, (NormalLine (Both l1 l2))
+          filterContext b@(Both {}) (c, AccuBottom, acc) =
+              if c < context then (c+1, AccuBottom, (NormalLine b):acc)
+                             else (c  , AccuBottom, (NormalLine b)
                                                     :((Prelude.take (context-1) acc)
                                                     ++ [Separator]
                                                     ++ (Prelude.drop (context+1) acc)))
-          filterContext (Both l1 l2) (c, AccuTop, acc) =
-              if c < context then (c+1, AccuTop   , (NormalLine (Both l1 l2)):acc)
-                             else (0  , AccuBottom, (NormalLine (Both l1 l2)):acc)
+          filterContext b@(Both {}) (c, AccuTop, acc) =
+              if c < context then (c+1, AccuTop   , (NormalLine b):acc)
+                             else (0  , AccuBottom, (NormalLine b):acc)
           filterContext element (_, _, acc) =
               (0, AccuTop, (NormalLine element):acc)
 
@@ -281,8 +281,8 @@ diffGetContext context list =
           startWithSeparator (Separator:_) = True
           startWithSeparator ((NormalLine l):xs) =
               case l of
-                  (Both _ _) -> startWithSeparator xs
-                  _          -> False
+                  Both {} -> startWithSeparator xs
+                  _       -> False
 
           removeTrailingBoth :: [FilteredDiff] -> [FilteredDiff]
           removeTrailingBoth diffList =
diff --git a/Data/Git/Diff/Patience.hs b/Data/Git/Diff/Patience.hs
new file mode 100644
index 0000000000000000000000000000000000000000..9aa329ae124636755cc41e870404779352f48e9c
--- /dev/null
+++ b/Data/Git/Diff/Patience.hs
@@ -0,0 +1,108 @@
+-- loosely based on the patience-0.1.1 package which is:
+--
+--     Copyright (c) Keegan McAllister 2011
+--
+module Data.Git.Diff.Patience
+    ( Item(..)
+    , diff
+    ) where
+
+import           Data.List
+import           Data.Function (on)
+import qualified Data.Map      as M
+import qualified Data.IntMap   as IM
+
+data Card a = Card !Int a !(Maybe (Card a))
+
+-- sort using patience making stack of card with the list of elements,
+-- then take the highest stack (maxView) and flatten the path back into a list
+-- to get the longest increasing path
+longestIncreasing :: [(Int,a)] -> [(Int,a)]
+longestIncreasing =
+      maybe [] (flatten . head . fst)
+    . IM.maxView
+    . foldl' ins IM.empty
+  where
+    ins :: IM.IntMap [Card a] -> (Int, a) -> IM.IntMap [Card a]
+    ins m (x,a) =
+        case IM.minViewWithKey gt of
+            Nothing        -> IM.insert x [new] m
+            Just ((k,_),_) ->
+                case IM.updateLookupWithKey (\_ _ -> Nothing) k m of
+                    (Just v, mm) -> IM.insert x (new : v) mm
+                    (Nothing, _) -> m
+      where
+            (lt, gt) = IM.split x m
+            prev = (head . fst) `fmap` IM.maxView lt
+            new  = Card x a prev
+
+    flatten :: Card a -> [(Int, a)]
+    flatten (Card x a c) = (x,a) : maybe [] flatten c
+
+-- Type for decomposing a diff problem.  We either have two
+-- lines that match, or a recursive subproblem.
+data Piece a =
+      Match !a !a
+    | Diff [a] [a]
+    deriving (Show)
+
+-- Get the longest common subsequence
+lcs :: Ord t => [t] -> [t] -> [Piece t]
+lcs ma mb =
+      chop ma mb
+    $ longestIncreasing
+    $ sortBy (compare `on` snd)
+    $ M.elems
+    $ M.intersectionWith (,) (unique ma) (unique mb)
+  where
+    unique = M.mapMaybe id . foldr ins M.empty . zip [0..]
+      where
+        ins (a,x) = M.insertWith (\_ _ -> Nothing) x (Just a)
+
+    -- Subdivides a diff problem according to the indices of matching lines.
+    chop :: [t] -> [t] -> [(Int,Int)] -> [Piece t]
+    chop xs ys []
+        | null xs && null ys = []
+        | otherwise = [Diff xs ys]
+    chop xs ys ((nx,ny):ns) =
+        let (xsr, (x : xse)) = splitAt nx xs
+            (ysr, (y : yse)) = splitAt ny ys
+         in  Diff xse yse : Match x y : chop xsr ysr ns
+
+-- | An element of a computed difference.
+data Item t =
+      Old  !t
+    | New  !t
+    | Both !t !t
+    deriving (Show,Eq)
+
+instance Functor Item where
+    fmap f (Old  x)   = Old  (f x)
+    fmap f (New  x)   = New  (f x)
+    fmap f (Both x y) = Both (f x) (f y)
+
+-- | The difference between two lists using the patience algorithm
+diff :: Ord t => [t] -> [t] -> [Item t]
+diff = matchPrefix []
+  where
+    -- match the prefix between old and new document
+    matchPrefix acc (x:xs) (y:ys)
+        | x == y    = Both x y : matchPrefix acc xs ys
+    matchPrefix acc l r = matchSuffix acc (reverse l) (reverse r)
+
+    -- match the suffix between old and new document, accumulating the
+    -- matched item in a reverse accumulator to keep TCO
+    matchSuffix acc (x:xs) (y:ys)
+        | x == y = matchSuffix (Both x y : acc) xs ys
+    matchSuffix acc l r = diffInner (reverse acc) (reverse l) (reverse r)
+
+    -- prefix and suffix are striped, and now do the LCS
+    diffInner acc l r =
+        case lcs l r of
+            -- If we fail to subdivide, just record the chunk as is.
+            [Diff _ _] -> fmap Old l ++ fmap New r ++ acc
+            ps -> recur acc ps
+
+    recur acc [] = acc
+    recur acc (Match x y  : ps) = recur (Both x y : acc) ps
+    recur acc (Diff xs ys : ps) = recur [] ps ++ matchPrefix acc xs ys
diff --git a/git.cabal b/git.cabal
index ab69667820c44c41c4741bae35ed4f30e7347d39..f0ee161a19f7a7cadae08d1e3025fe23e7bdebfd 100644
--- a/git.cabal
+++ b/git.cabal
@@ -40,7 +40,6 @@ Library
                    , hourglass >= 0.2
                    , unix-compat
                    , utf8-string
-                   , patience
                    -- to remove
                    , system-filepath
                    , system-fileio
@@ -58,6 +57,7 @@ Library
                      Data.Git.Revision
                      Data.Git.Repository
                      Data.Git.Diff
+                     Data.Git.Diff.Patience
   Other-modules:     Data.Git.Internal
                      Data.Git.Imports
                      Data.Git.OS