diff --git a/Tests/test-filediff.hs b/Tests/test-filediff.hs
--- a/Tests/test-filediff.hs
+++ b/Tests/test-filediff.hs
@@ -531,6 +531,65 @@
     directoriesEqual <- areDirectoriesEqual "a" "b"
     (@?) directoriesEqual "Directories not equal after application"
 
+-- assorted
+
+setUpRelativePathTest :: IO ()
+setUpRelativePathTest = do
+    D.createDirectory "a"
+    D.createDirectory "_"
+    D.createDirectory "_/b"
+
+    D.setCurrentDirectory "a"
+    createFileWithContents "a" "a"  
+    D.setCurrentDirectory ".."
+
+    D.setCurrentDirectory "_/b"
+    createFileWithContents "a" "b"
+    D.setCurrentDirectory "../.."
+
+relativePathExpectedDiff :: F.Diff
+relativePathExpectedDiff = F.Diff {
+    F.filediffs =
+        [ F.Filediff
+            { F.base = "a"
+            , F.comp = "a"
+            , F.change = F.Mod $ SeqDiff [0] [(0, T.pack "b")] } ]
+    }
+
+testRelativePathness :: Assertion
+testRelativePathness = do
+    setUpRelativePathTest
+
+    let expectedDiff = relativePathExpectedDiff
+    actualDiff <- F.diffDirectories "a" "_/b"
+    actualDiff @?= expectedDiff
+
+testRelativePathnessEdgeCases :: Assertion
+testRelativePathnessEdgeCases = do
+    setUpRelativePathTest
+    test "a"  "_/b"
+    test "a/" "_/b"
+    test "a"  "_/b/"
+    test "a/" "_/b/"
+    test "./a"  "_/b"
+    test "./a/" "_/b"
+    test "./a"  "_/b/"
+    test "./a/" "_/b/"
+    test "a"  "./_/b"
+    test "a/" "./_/b"
+    test "a"  "./_/b/"
+    test "a/" "./_/b/"
+    test "./a"  "./_/b"
+    test "./a/" "./_/b"
+    test "./a"  "./_/b/"
+    test "./a/" "./_/b/"
+    test "./a/" "./_/b/"
+    where
+        test :: FilePath -> FilePath -> Assertion
+        test a b = do
+            actualDiff <- F.diffDirectories a b
+            actualDiff @?= relativePathExpectedDiff
+
 -- tests
 
 tests :: TestTree
@@ -636,6 +695,14 @@
     , testCase
         "Testing directory diffing composition"
         (runTest testDirectoryDiffComposition)
+
+    -- assorted
+    , testCase
+        "Testing that paths are relative"
+        (runTest testRelativePathness)
+    , testCase
+        "Testing that paths are relative (edge cases)"
+        (runTest testRelativePathnessEdgeCases)
     ]
 
 main :: IO ()
diff --git a/filediff.cabal b/filediff.cabal
--- a/filediff.cabal
+++ b/filediff.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                filediff
-version:             0.1.0.4
+version:             0.1.0.5
 synopsis:            Diffing and patching module
 description:         `filediff` is a Haskell library for creating diffs, and applying diffs to files and directories.
 homepage:            https://github.com/bgwines/filediff
diff --git a/src/Filediff.hs b/src/Filediff.hs
--- a/src/Filediff.hs
+++ b/src/Filediff.hs
@@ -41,8 +41,12 @@
     , createFileWithContents
     , dropUntil
     , removeFirstPathComponent
+    , removePathComponents
     , getDirectoryContentsRecursiveSafe
-    , isPrefix)
+    , isPrefix
+    , dropPrefix
+    , dropInitialSlash
+    , dropTrailingSlash )
 
 -- * basic operations
 
@@ -106,7 +110,7 @@
 -- `[FilePath]` parameter refers to the first `FilePath` parameter,
 -- and same for the second, respectively.
 diffDirectoriesWithIgnoredSubdirs :: FilePath -> FilePath -> [FilePath] -> [FilePath] -> IO Diff
-diffDirectoriesWithIgnoredSubdirs a b aToIgnore bToIgnore = do
+diffDirectoriesWithIgnoredSubdirs a' b' aToIgnore bToIgnore = do
     aIsFile <- D.doesFileExist a
     bIsFile <- D.doesFileExist b
     when (aIsFile || bIsFile) $ error $ "One or both of " ++ a ++ " and " ++ b ++ "is not a directory, but a file."
@@ -122,10 +126,16 @@
 
     bOnlyDiffs <- getDiffs $ bContents \\ aContents
 
-    let allDiffs = map removeFirstPathComponentFromDiff $ intersectionDiffs ++ aOnlyDiffs ++ bOnlyDiffs
+    let allDiffs = map makeRelative $ intersectionDiffs ++ aOnlyDiffs ++ bOnlyDiffs
 
     return $ Diff allDiffs
     where
+        a :: FilePath
+        a = dropTrailingSlash a'
+
+        b :: FilePath
+        b = dropTrailingSlash b'
+
         -- | `x` is the prefix of the "base" of the diff; `y` is the
         -- | "compare".
         getDiffs :: [FilePath] -> IO [Filediff]
@@ -136,11 +146,11 @@
         isIdentityFileDiff :: Filediff -> Bool
         isIdentityFileDiff = (==) mempty . change
 
-        removeFirstPathComponentFromDiff :: Filediff -> Filediff
-        removeFirstPathComponentFromDiff (Filediff base comp change) =
+        makeRelative :: Filediff -> Filediff
+        makeRelative (Filediff base comp change) =
             Filediff
-                (removeFirstPathComponent base)
-                (removeFirstPathComponent comp)
+                (dropInitialSlash $ dropPrefix a base)
+                (dropInitialSlash $ dropPrefix b comp)
                 change
 
         shouldIgnore :: [FilePath] -> FilePath -> Bool
diff --git a/src/Filediff/Types.hs b/src/Filediff/Types.hs
--- a/src/Filediff/Types.hs
+++ b/src/Filediff/Types.hs
@@ -38,7 +38,6 @@
 } deriving (Eq, Show, Generic)
 
 -- | The types and sets of changes possible between two files.
--- `CompositionAddDel` is hack to make `mappend` work properly :/
 data FileChange
     = Del (SeqDiff Line)
     | Mod (SeqDiff Line)
diff --git a/src/Filediff/Utils.hs b/src/Filediff/Utils.hs
--- a/src/Filediff/Utils.hs
+++ b/src/Filediff/Utils.hs
@@ -9,11 +9,17 @@
 , removeDotDirs
 , createFileWithContents
 , removeFirstPathComponent
+, removePathComponents
 , getDirectoryContentsRecursiveSafe
 
--- * list operations
+  -- * file path formatting
+, dropInitialSlash
+, dropTrailingSlash
+
+  -- * list operations
 , dropUntil
 , isPrefix
+, dropPrefix
 ) where
 
 import Data.List ((\\), inits)
@@ -85,6 +91,16 @@
          then error "path without '/' in it"
          else tail . dropUntil ((==) '/') $ path
 
+-- | Removes the k oldest ancestors from a path component, e.g.
+-- |
+-- |     > removePathComponents 2 "a/b/c"
+-- |     "c"
+removePathComponents :: Int -> FilePath -> FilePath
+removePathComponents k
+    = last
+    . take k
+    . iterate removeFirstPathComponent
+
 -- | Gets paths to all files in or in subdirectories of the
 -- | specified directory. Returned paths are relative to the
 -- | given directory.
@@ -96,9 +112,8 @@
         then directory
         else directory </> ""
     let numPathComponents = length . filter ((==) '/') $ directoryWithTrailingSlash
-    let removePathComponents = last . take (numPathComponents + 1) . iterate removeFirstPathComponent
 
-    return . map removePathComponents $ contents
+    return . map (removePathComponents $ numPathComponents + 1) $ contents
 
 getDirectoryContentsRecursiveSafe' :: FilePath -> IO [FilePath]
 getDirectoryContentsRecursiveSafe' directory = do
@@ -116,6 +131,20 @@
 
             return $ files ++ recFiles
 
+-- * file path formatting
+
+-- | If the parameter has a '/' as its first character, drop it.
+dropInitialSlash :: String -> String
+dropInitialSlash ('/':s) = s
+dropInitialSlash s = s
+
+-- | If the parameter has a '/' as its last character, drop it.
+dropTrailingSlash :: String -> String
+dropTrailingSlash [] = []
+dropTrailingSlash s = if last s == '/'
+    then init s
+    else s
+
 -- * list operations
 
 -- | Drops elements from the given list until the predicate function
@@ -130,3 +159,10 @@
 -- | (intended to be used infix)
 isPrefix :: (Eq a) => [a] -> [a] -> Bool
 a `isPrefix` b = (==) (length a) . length . takeWhile id $ zipWith (==) a b
+
+-- | assumes `a` is a prefix of `b`; errors if false
+dropPrefix :: (Eq a) => [a] -> [a] -> [a]
+dropPrefix [] bs = bs
+dropPrefix (a:as) (b:bs)
+    | a /= b = error "not a prefix"
+    | otherwise = dropPrefix as bs
