diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,13 @@
+git-annex (6.20161031) unstable; urgency=medium
+
+  * Assistant, repair: Fix ignoring of git fsck errors due to
+    duplicate file entries in tree objects.
+  * Linux standalone: Fix location of locale files in the bundle.
+  * Fix reversion in 6.20161012 that prevented adding files with a space
+    in their name.
+
+ -- Joey Hess <id@joeyh.name>  Mon, 31 Oct 2016 18:55:59 -0400
+
 git-annex (6.20161027) unstable; urgency=medium
 
   * lock, smudge: Fix edge cases where data loss could occur in v6 mode
diff --git a/Git/CatFile.hs b/Git/CatFile.hs
--- a/Git/CatFile.hs
+++ b/Git/CatFile.hs
@@ -109,17 +109,18 @@
 	send to = hPutStrLn to (fromRef object)
 
 parseResp :: Ref -> String -> Maybe ParsedResp
-parseResp object l = case words l of
-	[sha, objtype, size]
-		| length sha == shaSize ->
-			case (readObjectType objtype, reads size) of
-				(Just t, [(bytes, "")]) -> 
-					Just $ ParsedResp (Ref sha) bytes t
-				_ -> Nothing
-		| otherwise -> Nothing
-	_
-		| l == fromRef object ++ " missing" -> Just DNE
-		| otherwise -> Nothing
+parseResp object l 
+	| " missing" `isSuffixOf` l -- less expensive than full check
+		&& l == fromRef object ++ " missing" = Just DNE
+	| otherwise = case words l of
+		[sha, objtype, size]
+			| length sha == shaSize ->
+				case (readObjectType objtype, reads size) of
+					(Just t, [(bytes, "")]) -> 
+						Just $ ParsedResp (Ref sha) bytes t
+					_ -> Nothing
+			| otherwise -> Nothing
+		_ -> Nothing
 
 {- Gets a list of files and directories in a tree. (Not recursive.) -}
 catTree :: CatFileHandle -> Ref -> IO [(FilePath, FileMode)]
diff --git a/Git/Fsck.hs b/Git/Fsck.hs
--- a/Git/Fsck.hs
+++ b/Git/Fsck.hs
@@ -5,6 +5,8 @@
  - Licensed under the GNU GPL version 3 or higher.
  -}
 
+{-# LANGUAGE BangPatterns #-}
+
 module Git.Fsck (
 	FsckResults(..),
 	MissingObjects,
@@ -25,8 +27,6 @@
 import qualified Data.Set as S
 import Control.Concurrent.Async
 
-type MissingObjects = S.Set Sha
-
 data FsckResults 
 	= FsckFoundMissing
 		{ missingObjects :: MissingObjects
@@ -35,6 +35,25 @@
 	| FsckFailed
 	deriving (Show)
 
+data FsckOutput 
+	= FsckOutput MissingObjects Truncated
+	| NoFsckOutput
+	| AllDuplicateEntriesWarning
+
+type MissingObjects = S.Set Sha
+
+type Truncated = Bool
+
+instance Monoid FsckOutput where
+	mempty = NoFsckOutput
+	mappend (FsckOutput s1 t1) (FsckOutput s2 t2) = FsckOutput (S.union s1 s2) (t1 || t2)
+	mappend (FsckOutput s t) _ = FsckOutput s t
+	mappend _ (FsckOutput s t) = FsckOutput s t
+	mappend NoFsckOutput NoFsckOutput = NoFsckOutput
+	mappend AllDuplicateEntriesWarning AllDuplicateEntriesWarning = AllDuplicateEntriesWarning
+	mappend AllDuplicateEntriesWarning NoFsckOutput = AllDuplicateEntriesWarning
+	mappend NoFsckOutput AllDuplicateEntriesWarning = AllDuplicateEntriesWarning
+
 {- Runs fsck to find some of the broken objects in the repository.
  - May not find all broken objects, if fsck fails on bad data in some of
  - the broken objects it does find.
@@ -58,18 +77,24 @@
 			{ std_out = CreatePipe
 			, std_err = CreatePipe
 			}
-	(bad1, bad2) <- concurrently
-		(readMissingObjs maxobjs r supportsNoDangling (stdoutHandle p))
-		(readMissingObjs maxobjs r supportsNoDangling (stderrHandle p))
+	(o1, o2) <- concurrently
+		(parseFsckOutput maxobjs r supportsNoDangling (stdoutHandle p))
+		(parseFsckOutput maxobjs r supportsNoDangling (stderrHandle p))
 	fsckok <- checkSuccessProcess pid
-	let truncated = S.size bad1 == maxobjs || S.size bad1 == maxobjs
-	let badobjs = S.union bad1 bad2
-
-	if S.null badobjs && not fsckok
-		then return FsckFailed
-		else return $ FsckFoundMissing badobjs truncated
+	case mappend o1 o2 of
+		FsckOutput badobjs truncated
+			| S.null badobjs && not fsckok -> return FsckFailed
+			| otherwise -> return $ FsckFoundMissing badobjs truncated
+		NoFsckOutput
+			| not fsckok -> return FsckFailed
+			| otherwise -> return noproblem
+		-- If all fsck output was duplicateEntries warnings,
+		-- the repository is not broken, it just has some unusual
+		-- tree objects in it. So ignore nonzero exit status.
+		AllDuplicateEntriesWarning -> return noproblem
   where
 	maxobjs = 10000
+	noproblem = FsckFoundMissing S.empty False
 
 foundBroken :: FsckResults -> Bool
 foundBroken FsckFailed = True
@@ -87,10 +112,18 @@
 findMissing :: [Sha] -> Repo -> IO MissingObjects
 findMissing objs r = S.fromList <$> filterM (`isMissing` r) objs
 
-readMissingObjs :: Int -> Repo -> Bool -> Handle -> IO MissingObjects
-readMissingObjs maxobjs r supportsNoDangling h = do
-	objs <- take maxobjs . findShas supportsNoDangling <$> hGetContents h
-	findMissing objs r
+parseFsckOutput :: Int -> Repo -> Bool -> Handle -> IO FsckOutput
+parseFsckOutput maxobjs r supportsNoDangling h = do
+	ls <- lines <$> hGetContents h
+	if null ls
+		then return NoFsckOutput
+		else if all ("duplicateEntries" `isInfixOf`) ls
+			then return AllDuplicateEntriesWarning
+			else do
+				let shas = findShas supportsNoDangling ls
+				let !truncated = length shas > maxobjs
+				missingobjs <- findMissing (take maxobjs shas) r
+				return $ FsckOutput missingobjs truncated
 
 isMissing :: Sha -> Repo -> IO Bool
 isMissing s r = either (const True) (const False) <$> tryIO dump
@@ -100,12 +133,10 @@
 		, Param (fromRef s)
 		] r
 
-findShas :: Bool -> String -> [Sha]
-findShas supportsNoDangling = catMaybes . map extractSha . concat . map words . filter wanted . lines
+findShas :: Bool -> [String] -> [Sha]
+findShas supportsNoDangling = catMaybes . map extractSha . concat . map words . filter wanted
   where
 	wanted l
-		-- Skip lines like "error in tree <sha>: duplicateEntries: contains duplicate file entries"
-		| "duplicateEntries" `isInfixOf` l = False
 		| supportsNoDangling = True
 		| otherwise = not ("dangling " `isPrefixOf` l)
 
diff --git a/git-annex.cabal b/git-annex.cabal
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -1,5 +1,5 @@
 Name: git-annex
-Version: 6.20161027
+Version: 6.20161031
 Cabal-Version: >= 1.8
 License: GPL-3
 Maintainer: Joey Hess <id@joeyh.name>
