Recent changes to this wiki:

Added a comment
diff --git a/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_4_8323e9160d81a4a65f2ca545c4469869._comment b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_4_8323e9160d81a4a65f2ca545c4469869._comment
new file mode 100644
index 000000000..274892510
--- /dev/null
+++ b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_4_8323e9160d81a4a65f2ca545c4469869._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="erics"
+ avatar="http://cdn.libravatar.org/avatar/6e5f74c742128e5d98fd672ed6ea4865"
+ subject="comment 4"
+ date="2021-05-10T22:06:02Z"
+ content="""
+May I suggest a *what references this key* command?  With that, I'd have been able to figure out for myself what I'd done wrong.
+"""]]

Added a comment: D'oh!
diff --git a/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_3_7cc944d96f4620e98fe22a554684ad22._comment b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_3_7cc944d96f4620e98fe22a554684ad22._comment
new file mode 100644
index 000000000..8c35fe084
--- /dev/null
+++ b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_3_7cc944d96f4620e98fe22a554684ad22._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="erics"
+ avatar="http://cdn.libravatar.org/avatar/6e5f74c742128e5d98fd672ed6ea4865"
+ subject="D'oh!"
+ date="2021-05-10T21:26:25Z"
+ content="""
+\"Is it in use in git's index?\"
+
+That was it; after *git reset*, the file is now again reported as unused.
+
+Thanks, and sorry for the noise.
+"""]]

mention index mode explicitly
diff --git a/doc/git-annex-unused.mdwn b/doc/git-annex-unused.mdwn
index faca68165..e4a4d808f 100644
--- a/doc/git-annex-unused.mdwn
+++ b/doc/git-annex-unused.mdwn
@@ -9,7 +9,8 @@ git annex unused
 # DESCRIPTION
 
 Checks the annex for data that does not correspond to any files present
-in any tag or branch, and prints a numbered list of the data.
+in any tag or branch, or in the git index, and prints a numbered list
+of the data.
 
 After running this command, you can use the `--unused` option with many 
 other git-annex commands to operate on all the unused data that was found.
@@ -33,10 +34,10 @@ For example, to move all unused data to origin:
 
 * `--used-refspec=+ref:-ref`
 
-  By default, any data that the work tree uses, or that any refs in the git
+  By default, any data that the git index uses, or that any refs in the git
   repository point to is considered to be used. If you only want to use
   some refs, you can use this option to specify the ones to use. Data that
-  is not in the specified refs (and not used by the work tree) will then be
+  is not in the specified refs (and not used by the index) will then be
   considered unused.
 
   The git configuration annex.used-refspec can be used to configure

comment
diff --git a/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_1_30217e593a04cefa30619025d0a58108._comment b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_1_30217e593a04cefa30619025d0a58108._comment
new file mode 100644
index 000000000..979211ee7
--- /dev/null
+++ b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_1_30217e593a04cefa30619025d0a58108._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-10T19:04:00Z"
+ content="""
+Is it in use in git's index? git-annex addunused adds a link to the working
+tree, and also stages it in the index. You said
+"I rm'ed the symlink", but that would leave it in the index, so still used.
+
+(It's also theoretically possible for git-annex unused to incorrectly
+decide something is unused that is not -- it uses a bloom filter which can
+have false positives -- but this is highly unlikely unless your repo has
+a huge number of files in it. The annex.bloomaccuracy and annex.bloomaccuracy
+configs can be used to tweak the bloom filter.)
+"""]]

Added a comment
diff --git a/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_1_6793035e1c0fb329b3094bf66a982fa3._comment b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_1_6793035e1c0fb329b3094bf66a982fa3._comment
new file mode 100644
index 000000000..2a7682371
--- /dev/null
+++ b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__/comment_1_6793035e1c0fb329b3094bf66a982fa3._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="kyle"
+ avatar="http://cdn.libravatar.org/avatar/7d6e85cde1422ad60607c87fa87c63f3"
+ subject="comment 1"
+ date="2021-05-10T19:05:57Z"
+ content="""
+> I rm'ed the symlink, expecting git annex unused to again report K as
+> unused.  But it doesn't; it still reports no unused files.
+
+That's odd.  Did you also remove it from the index (`git rm`)?
+
+> git log --stat --no-textconv -S'K'
+
+Perhaps try with `--all` to do a wider search, though given what you
+said above (that is was reported as unused before using `addunused`) my
+bet would be on the index.
+
+"""]]

split out common options to its own page and mention it on each subcommand page
Sometimes users would get confused because an option they were looking
for was not mentioned on a subcommand's man page, and they had not
noticed that the main git-annex man page had a list of common options.
This change lets each subcommand mention the common options, similarly
to how the matching options are handled.
This commit was sponsored by Svenne Krap on Patreon.
diff --git a/doc/git-annex-add.mdwn b/doc/git-annex-add.mdwn
index 7d87a4236..c3e15e12f 100644
--- a/doc/git-annex-add.mdwn
+++ b/doc/git-annex-add.mdwn
@@ -106,6 +106,8 @@ annexed content, and other symlinks.
   Makes the `--batch` input be delimited by nulls instead of the usual
   newlines.
 
+* Also the [[git-annex-common-options]](1) can be used.
+
 # SEE ALSO
 
 [[git-annex]](1)
diff --git a/doc/git-annex-addunused.mdwn b/doc/git-annex-addunused.mdwn
index 3dbddd641..2d948bdda 100644
--- a/doc/git-annex-addunused.mdwn
+++ b/doc/git-annex-addunused.mdwn
@@ -13,6 +13,10 @@ as listed by the last `git annex unused`.
 
 The files will have names starting with "unused."
 
+# OPTIONS
+
+* The [[git-annex-common-options]](1) can be used.
+
 # SEE ALSO
 
 [[git-annex]](1)
diff --git a/doc/git-annex-addurl.mdwn b/doc/git-annex-addurl.mdwn
index fe5b1627c..b067c9c34 100644
--- a/doc/git-annex-addurl.mdwn
+++ b/doc/git-annex-addurl.mdwn
@@ -130,6 +130,8 @@ be used to get better filenames.
   Messages that would normally be output to standard error are included in
   the json instead.
 
+* Also the [[git-annex-common-options]](1) can be used.
+
 # CAVEATS
 
 If annex.largefiles is configured, and does not match a file, `git annex
diff --git a/doc/git-annex-adjust.mdwn b/doc/git-annex-adjust.mdwn
index 97b7518a8..644e9fb26 100644
--- a/doc/git-annex-adjust.mdwn
+++ b/doc/git-annex-adjust.mdwn
@@ -109,6 +109,8 @@ and will also propagate commits back to the original branch.
   set the `annex.adjustedbranchrefresh` config. Or use `git-annex sync
   --content`, which updates the branch after transferring content.
 
+* Also the [[git-annex-common-options]](1) can be used.
+
 # SEE ALSO
 
 [[git-annex]](1)
diff --git a/doc/git-annex-assistant.mdwn b/doc/git-annex-assistant.mdwn
index 98cdab4d0..18f9341e2 100644
--- a/doc/git-annex-assistant.mdwn
+++ b/doc/git-annex-assistant.mdwn
@@ -40,6 +40,8 @@ and automatically syncs them to other remotes.
   The complement to --autostart; stops all running daemons in the
   repositories listed in the autostart file.
 
+* Also the [[git-annex-common-options]](1) can be used.
+
 # SEE ALSO
 
 [[git-annex]](1)
diff --git a/doc/git-annex-calckey.mdwn b/doc/git-annex-calckey.mdwn
index b7f546454..616e6aa66 100644
--- a/doc/git-annex-calckey.mdwn
+++ b/doc/git-annex-calckey.mdwn
@@ -34,6 +34,8 @@ For example, to force use of the SHA1 backend:
   Makes the `--batch` input be delimited by nulls instead of the usual
   newlines.
 
+* Also the [[git-annex-common-options]](1) can be used.
+
 # SEE ALSO
 
 [[git-annex]](1)
diff --git a/doc/git-annex-checkpresentkey.mdwn b/doc/git-annex-checkpresentkey.mdwn
index baa5ba47c..5d4d4b971 100644
--- a/doc/git-annex-checkpresentkey.mdwn
+++ b/doc/git-annex-checkpresentkey.mdwn
@@ -27,6 +27,8 @@ the special exit code 100 is used, and an error message is output to stderr.
   read from stdin, and a line is output with "1" if the key is verified to
   be present, and "0" otherwise.
 
+* Also the [[git-annex-common-options]](1) can be used.
+
 # SEE ALSO
 
 [[git-annex]](1)
diff --git a/doc/git-annex-common-options.mdwn b/doc/git-annex-common-options.mdwn
new file mode 100644
index 000000000..ec9b56b85
--- /dev/null
+++ b/doc/git-annex-common-options.mdwn
@@ -0,0 +1,136 @@
+# NAME
+
+git-annex-common-options - options supported by all git-annex commands
+
+# DESCRIPTION
+
+These common options are accepted by all git-annex commands, and
+may not be explicitly listed on their individual man pages.
+(Many commands also accept the [[git-annex-matching-options]](1).)
+
+# OPTIONS
+
+* `--force`
+
+  Force unsafe actions, such as dropping a file's content when no other
+  source of it can be verified to still exist, or adding ignored files.
+  Use with care.
+
+* `--fast`
+
+  Avoid some expensive operations normally performed by a command.
+  What is avoided depends on the command, see individual command's man
+  pages for details.
+
+* `--quiet`
+
+  Avoid the default verbose display of what is done; only show errors.
+
+* `--verbose`
+
+  Enable verbose display.
+
+* `--debug`
+
+  Display debug messages.
+
+* `--no-debug`
+
+  Disable display of debug messages.
+
+* `--debugfilter=name[,name..]`
+
+  When debug message display has been enabled by `--debug`, this filters
+  the debug messages that are displayed to ones coming from modules with
+  the specified names.
+  
+  To find the names of modules, see the full debug output, which includes
+  the module name, eg "(Utility.Process)"
+
+  The full module name does not need to be
+  specified when using this, a substring of the name will do.
+
+  For example, `--debugfilter=Process,External` will display debugging
+  output when git-annex runs processes, and when it communicates with
+  external special remotes.
+
+* `--numcopies=n`
+
+  Overrides the numcopies setting.
+
+  Note that setting numcopies to 0 is very unsafe.
+
+* `--mincopies=n`
+
+  Overrides the mincopies setting.
+
+  Note that setting mincopies to 0 is very unsafe.
+
+* `--time-limit=time`
+
+  Limits how long a git-annex command runs. The time can be something
+  like "5h", or "30m" or even "45s" or "10d".
+
+  Note that git-annex may continue running a little past the specified
+  time limit, in order to finish processing a file.
+
+  Also, note that if the time limit prevents git-annex from doing all it
+  was asked to, it will exit with a special code, 101.
+
+* `--semitrust=repository`
+* `--untrust=repository`
+
+  Overrides trust settings for a repository. May be specified more than once.
+
+  The repository should be specified using the name of a configured remote,
+  or the UUID or description of a repository.
+
+* `--trust=repository`
+
+  This used to override trust settings for a repository, but now will
+  not do so, because trusting a repository can lead to data loss,
+  and data loss is now only enabled when using the `--force` option.
+
+* `--trust-glacier`
+
+  This used to override trust settings for Glacier special remotes,
+  but now will not do so, because it could lead to data loss,
+  and data loss is now only enabled when using the `--force` option.
+
+* `--backend=name`
+

(Diff truncated)
comment
diff --git a/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_5_789e8ada06063f6a1c6d6358180dc202._comment b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_5_789e8ada06063f6a1c6d6358180dc202._comment
new file mode 100644
index 000000000..72add2bfa
--- /dev/null
+++ b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_5_789e8ada06063f6a1c6d6358180dc202._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2021-05-10T17:21:14Z"
+ content="""
+Yes, I seem to have been able to fix it like that. Also added a test case
+to make sure the largefiles conversion recipes keep working.
+
+Of course it's always possible there are other cases I've not thought of..
+"""]]

diff --git a/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__.mdwn b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__.mdwn
new file mode 100644
index 000000000..7a7a5d857
--- /dev/null
+++ b/doc/forum/How_can_I_determine_why_a_given_file_is___34__used__34____63__.mdwn
@@ -0,0 +1,25 @@
+I have a particular annexed file (call its key *K*), and I'm trying to find out why *git annex* considers it in-use.
+
+Joey's comment to [[Dead repo content is not considered unused]] does a good job of explaining why, in theory, a file *might be* considered in-use.
+
+But how can I determine, in a particular case, why a given file *is* in-use?  I.e. how can I determine what's referencing it?
+
+Things I've tried:
+
+* *git annex unused --used-refspec=+foo*, where I'm certain that neither tag *foo* nor any of its ancestors references the file in question (that command doesn't report any unused files)
+
+* Verifying that there are now no symlinks to the annex object in question
+
+* *git log --stat --no-textconv -S'K'* (which produces no output)
+
+Background:
+
+*git annex unused* listed *K* as unused.  I wanted to see what it was, so I did *git annex addunused* on it to create a symlink. (As expected, after this, *git annex unused* reported no unused files.)
+
+Having determined that the file was in fact no longer needed, I rm'ed the symlink, expecting *git annex unused* to again report *K* as unused.  But it doesn't; it still reports no unused files.
+
+I'm not aware of having done anything that would create a reference other than *addunused*'s new symlink, but clearly I did so without being aware of it...
+
+So I'm trying to figure out where that reference is, so I can stomp on it and then *git annex dropunused* to get rid of the file for good.
+
+Thanks.

comment
diff --git a/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_4_8d1ba01f4e25606b960023eab38ec483._comment b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_4_8d1ba01f4e25606b960023eab38ec483._comment
new file mode 100644
index 000000000..cd3d8215c
--- /dev/null
+++ b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_4_8d1ba01f4e25606b960023eab38ec483._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2021-05-10T16:43:00Z"
+ content="""
+Maybe the solution would be for `git annex add`, whenever it decides to
+add a file to git (due to --force-small or largefiles config), to drop the
+inode out of the keys database? I think that would make all of the cases
+described so far work.
+"""]]

comment
diff --git a/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_3_3c3c4b9ee0a99f0638717922785de675._comment b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_3_3c3c4b9ee0a99f0638717922785de675._comment
new file mode 100644
index 000000000..0bbb28fe7
--- /dev/null
+++ b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_3_3c3c4b9ee0a99f0638717922785de675._comment
@@ -0,0 +1,29 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2021-05-10T16:20:37Z"
+ content="""
+Well Lukey was right, fixing this causes other breakage. Here's
+the bug report about what my change broke:
+[[bugs/case_where_using_pathspec_with_git-commit_leaves_s]]
+
+As well as the case in that bug, [[tips/largefiles]] has a recipe to convert
+an annexed file to be stored in git, which the change broke. 
+The recipe has `git annex add --force-small` be run on a file, which in turn
+runs `git add` on the file, which runs the smudge filter. So if the smudge
+filter then sees an annexed inode and keeps it annexed, it is going against
+what the user is trying to do there.
+
+So the change has been reverted.
+
+I guess that both problems could be avoided by having git-annex add not run
+git add, but stage the file in the index itself. (IIRC there were some
+reasons to use git add there, to do with .gitignore.)
+
+But I'm doubtful now that all problems could be avoided. For one,
+consider what happens when the user follows the recipe to convert an
+annexed file to be stored in git, running `git annex add --force-small
+file`, which does store it in git. But then, if the smudge clean filter runs
+on the file later for any reason, it would still see a known annexed inode,
+and convert it back to being stored in the annex.
+"""]]

Revert "smudge: check for known annexed inodes before checking annex.largefiles"
This reverts commit 424bef6b6f43ba9e09b61faa337fc6c9104e1a1f.
This commit caused other buggy behavior unfortunately.
diff --git a/CHANGELOG b/CHANGELOG
index 4f73fbcec..b5d2290e4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,9 +2,6 @@ git-annex (8.20210429) UNRELEASED; urgency=medium
 
   * fromkey: Create an unlocked file when used in an adjusted branch
     where the file should be unlocked, or when configured by annex.addunlocked.
-  * smudge: Fix a case where an unlocked annexed file that annex.largefiles
-    does not match could get its unchanged content checked into git,
-    due to git running the smudge filter unecessarily.
   * Fix behavior of several commands, including reinject, addurl, and rmurl
     when given an absolute path to an unlocked file, or a relative path
     that leaves and re-enters the repository.
diff --git a/Command/Smudge.hs b/Command/Smudge.hs
index cbecd055f..4903ce4a4 100644
--- a/Command/Smudge.hs
+++ b/Command/Smudge.hs
@@ -168,26 +168,25 @@ clean file = do
 		filepath <- liftIO $ absPath file
 		return $ not $ dirContains repopath filepath
 
--- If annex.largefiles is configured (and not disabled by annex.gitaddtoannex
--- being set to false), matching files are added to the annex and the rest to
--- git.
+-- If annex.largefiles is configured, matching files are added to the
+-- annex. But annex.gitaddtoannex can be set to false to disable that.
 --
 -- When annex.largefiles is not configured, files are normally not
--- added to the annex, so will be added to git. However, if the file
--- is annexed in the index, keep it annexed. This prevents accidental
--- conversions when previously annexed files get modified and added.
+-- added to the annex, so will be added to git. But some heuristics
+-- are used to avoid bad behavior:
 --
--- In either case, if the file's inode is the same as one that was used
--- for annexed content before, annex it. And if the file is not annexed
--- in the index, and has the same content, leave it in git.
--- This handles cases such as renaming a file followed by git add,
--- which the user naturally expects to behave the same as git mv.
+-- If the file is annexed in the index, keep it annexed.
+-- This prevents accidental conversions.
+--
+-- Otherwise, when the file's inode is the same as one that was used for
+-- annexed content before, annex it. This handles cases such as renaming an
+-- unlocked annexed file followed by git add, which the user naturally
+-- expects to behave the same as git mv.
 shouldAnnex :: RawFilePath -> Maybe (Sha, FileSize, ObjectType) -> Maybe Key -> Annex Bool
-shouldAnnex file indexmeta moldkey = do
-	ifM (annexGitAddToAnnex <$> Annex.getGitConfig)
-		( checkunchanged $ checkmatcher checkwasannexed
-		, checkunchanged checkwasannexed
-		)
+shouldAnnex file indexmeta moldkey = ifM (annexGitAddToAnnex <$> Annex.getGitConfig)
+	( checkunchangedgitfile $ checkmatcher checkheuristics
+	, checkunchangedgitfile checkheuristics
+	)
   where
 	checkmatcher d
 		| dotfile file = ifM (getGitConfigVal annexDotFiles)
@@ -200,21 +199,14 @@ shouldAnnex file indexmeta moldkey = do
 			matcher <- largeFilesMatcher
 			checkFileMatcher' matcher file d
 	
-	checkwasannexed = pure $ isJust moldkey
+	checkheuristics = case moldkey of
+		Just _ -> return True
+		Nothing -> checkknowninode
 
-	isknownannexedinode = withTSDelta (liftIO . genInodeCache file) >>= \case
+	checkknowninode = withTSDelta (liftIO . genInodeCache file) >>= \case
 		Nothing -> pure False
 		Just ic -> Database.Keys.isInodeKnown ic =<< sentinalStatus
 
-	-- If the inode matches one known used for annexed content,
-	-- keep the file annexed. This handles a case where the file
-	-- has been annexed before, and the git is running the clean filter
-	-- again on it for whatever reason.
-	checkunchanged cont = ifM isknownannexedinode
-		( return True
-		, checkunchangedgitfile cont
-		)
-
 	-- This checks for a case where the file had been added to git
 	-- previously, not to the annex before, and its content is not
 	-- changed, but git is running the clean filter again on it
diff --git a/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn b/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn
index 862bb1fc8..a9d33dff6 100644
--- a/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn
+++ b/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn
@@ -115,3 +115,5 @@ Thanks for taking a look.
 
 [[!meta author=kyle]]
 [[!tag projects/datalad]]
+
+> commit reverted; [[done]] --[[Joey]]
diff --git a/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s/comment_1_a71ce38ec25075ac7037550094da2bf7._comment b/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s/comment_1_a71ce38ec25075ac7037550094da2bf7._comment
new file mode 100644
index 000000000..d4776c279
--- /dev/null
+++ b/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s/comment_1_a71ce38ec25075ac7037550094da2bf7._comment
@@ -0,0 +1,44 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-10T16:04:07Z"
+ content="""
+On the second `git annex add foo`, I see:
+
+	add foo (non-large file; adding content to git repository) ok
+
+Which seems right as far as the largefiles config goes.
+
+That in turn runs `git add`, which runs the smudge filter. Due to my change
+in [[!commit 424bef6b6]], the smudge filter then sees an inode it already
+knows (because the file was unlocked), and so it avoids adding the file to
+git, and leaves it annexed.
+
+I don't quite understand how the different ways of running git commit play
+into this, or how the file ends up, after the commit, to having a
+non-annexed file recorded in the index. I guess the smudge filter must
+end up being run again, and perhaps the [[!commit 424bef6b6]] change
+doesn't work then, but anyway the behavior before that point is already a
+problem.
+
+Another instance of I think the same problem is following the
+[[tips/largefiles]] recipe to convert an annexed file to git:
+
+	git init repo; cd repo; git annex init
+	echo foo > file
+	git annex add file
+	git commit -m add
+	git annex unlock file
+	git rm --cached file
+	git annex add --force-small file
+	git commit -m convert file
+
+This results in a commit that unlocked the file but leaves
+it annexed, and after the commit, git diff --cached shows that the index
+has staged a conversion from unlocked to stored in git. So very similar,
+and clearly [[!commit 424bef6b6]] cannot be allowed to cause that breakage,
+which does not even involve largefiles!
+
+So I've reverted the commit for now, and we can discuss next steps in the
+forum thread.
+"""]]

mention --all on fsck man page, and repurpose todo
diff --git a/doc/git-annex-fsck.mdwn b/doc/git-annex-fsck.mdwn
index 472c5a70a..4407f0c5e 100644
--- a/doc/git-annex-fsck.mdwn
+++ b/doc/git-annex-fsck.mdwn
@@ -110,6 +110,13 @@ better format.
   Messages that would normally be output to standard error are included in
   the json instead.
 
+* `--quiet`
+
+  Like all git-annex commands, this option makes only error and warning
+  messages be displayed. This is particularly useful with fsck, which
+  normally displays all the files it's checking even when there is no
+  problem with them.
+
 # SEE ALSO
 
 [[git-annex]](1)
diff --git a/doc/todo/fsck_option_to_only_show_broken.mdwn b/doc/todo/fsck_option_to_only_show_broken.mdwn
index cade432e4..f0ed31c85 100644
--- a/doc/todo/fsck_option_to_only_show_broken.mdwn
+++ b/doc/todo/fsck_option_to_only_show_broken.mdwn
@@ -1,3 +1,5 @@
 `git annex fsck` currently spams the terminal with all keys in a repo and prints `git-annex: fsck: n failed` at the end if errors occur. Finding these errors in a sea of `ok`s is not trivial however.
 
 A simple solution to this could be an fsck option which skips printing ok'd (and perhaps also dead) keys, i.e. `--no-ok` and `--no-dead`.
+
+[[!meta title="mention common options on per-command man pages"]]
diff --git a/doc/todo/fsck_option_to_only_show_broken/comment_3_77600b5ce57004e66f9fde7ac8386928._comment b/doc/todo/fsck_option_to_only_show_broken/comment_3_77600b5ce57004e66f9fde7ac8386928._comment
new file mode 100644
index 000000000..1c778a4ab
--- /dev/null
+++ b/doc/todo/fsck_option_to_only_show_broken/comment_3_77600b5ce57004e66f9fde7ac8386928._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2021-05-10T15:07:06Z"
+ content="""
+Normally the common options are not included in every command's man page
+because there are over 100 lines of them. However, I do think it's worth
+including --quiet on fsck's man page in this specific case and am doing
+that.
+
+Maybe individual command man pages should mention that there are
+also a bunch of common options. Perhaps those should be split out of the
+git-annex man page, like the git-annex-matching-options man page is
+handled.
+"""]]

comment and close
diff --git a/doc/bugs/assistant_tries_to_drop_all_files_on_startup.mdwn b/doc/bugs/assistant_tries_to_drop_all_files_on_startup.mdwn
index 11f1cbd45..8c0b561f0 100644
--- a/doc/bugs/assistant_tries_to_drop_all_files_on_startup.mdwn
+++ b/doc/bugs/assistant_tries_to_drop_all_files_on_startup.mdwn
@@ -51,3 +51,4 @@ failed
 ### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
 
 
+> notabug per my comment; [[done]] --[[Joey]]
diff --git a/doc/bugs/assistant_tries_to_drop_all_files_on_startup/comment_1_17f31c4230b84709b7c9ae777b2ebbd0._comment b/doc/bugs/assistant_tries_to_drop_all_files_on_startup/comment_1_17f31c4230b84709b7c9ae777b2ebbd0._comment
new file mode 100644
index 000000000..91436510c
--- /dev/null
+++ b/doc/bugs/assistant_tries_to_drop_all_files_on_startup/comment_1_17f31c4230b84709b7c9ae777b2ebbd0._comment
@@ -0,0 +1,33 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-10T14:53:34Z"
+ content="""
+Currently the assistant simply tries to drop when it thinks it's possible
+that the content may be droppable. It doesn't check if the drop is allowed
+before trying to drop. Because that would be redundant with the check
+that's done when actually dropping.
+
+I don't see anything dangerous about this, same as running `git annex drop`
+on lots of files and having them be preserved by numcopies is not
+dangerous.
+
+If it's a bug at all, it's only that it should be silent if
+it is unable to perform the drop due to numcopies. However, 
+making it silent about that also seems like it would make it harder to
+figure out what is preventing things from being dropping in situations
+where you do expect drops to happen.
+
+As in, ironically, your specific case! You have a transfer remote, which is
+having files pile up on it, despite them apparently having been transferred
+from it to both of the repos you want it to transfer them to. Since your
+local repo cannot access the other repo, it cannot verify it has the
+content and so leaves a copy on the transfer remote.
+
+If you had a problem with that transfer remote filling up, and nothing was
+ever logged about why it was not dropping from it, it would be hard to
+understand what was going on and how to fix it (eg by trusting the other
+repo, or adding it as a remote, or lowering numcopies to 1).
+
+So the logging seems like a good thing to me.
+"""]]

comment
diff --git a/doc/todo/Use_editorconfig_for_formatting_rules/comment_1_20e6d6467dcc9e4814c657355a7f2e74._comment b/doc/todo/Use_editorconfig_for_formatting_rules/comment_1_20e6d6467dcc9e4814c657355a7f2e74._comment
new file mode 100644
index 000000000..0d73fe2a1
--- /dev/null
+++ b/doc/todo/Use_editorconfig_for_formatting_rules/comment_1_20e6d6467dcc9e4814c657355a7f2e74._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-10T14:41:53Z"
+ content="""
+I guess you're talking about the elisp in [[coding_style]].
+
+editorconfig looks reasonable though pretty limited in what it can do. 
+I like that plugins are included in Debian. If you want to develop
+an editorconfig file we can add it to git-annex.
+"""]]

comment
diff --git a/doc/bugs/Git_repos_corrupt_themselves/comment_1_c7fbc3da4404fb33a4b0babf068dc4d3._comment b/doc/bugs/Git_repos_corrupt_themselves/comment_1_c7fbc3da4404fb33a4b0babf068dc4d3._comment
new file mode 100644
index 000000000..001f6a85e
--- /dev/null
+++ b/doc/bugs/Git_repos_corrupt_themselves/comment_1_c7fbc3da4404fb33a4b0babf068dc4d3._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-10T14:25:20Z"
+ content="""
+git-annex does not write directly to your git repository; all writes go via
+git. So it is hard to see how any corruption like this could be due to a
+bug in git-annex.
+
+What it usually is caused by is a filesystem losing data, eg because of an
+unclean shutdown or a crash, or sometimes because of a disk error.
+
+Setting the git config core.fsyncObjectFiles may help. Configuring the
+filesystem to write data to disk more promptly (eg enabling journalling of
+file contents) may help.
+
+`git-annex repair --force` may be able to recover from this situation.
+
+The "evacuate: strange closure" error does seem notable, something strange
+is going on in the memory of git-annex. Presumably due to either a compiler
+bug or some kind of memory problem.
+"""]]

Added a comment
diff --git a/doc/todo/fsck_option_to_only_show_broken/comment_2_1aeb905eb97a1f121fed3d182a22981c._comment b/doc/todo/fsck_option_to_only_show_broken/comment_2_1aeb905eb97a1f121fed3d182a22981c._comment
new file mode 100644
index 000000000..072f79ec3
--- /dev/null
+++ b/doc/todo/fsck_option_to_only_show_broken/comment_2_1aeb905eb97a1f121fed3d182a22981c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 2"
+ date="2021-05-10T14:13:55Z"
+ content="""
+Thanks, that's exactly what I'm looking for!
+
+It's not in the git-annex-fsck manpage though for some reason.
+"""]]

Added a comment
diff --git a/doc/todo/fsck_option_to_only_show_broken/comment_1_e42a2cfa898fed9203168a6f68218ecc._comment b/doc/todo/fsck_option_to_only_show_broken/comment_1_e42a2cfa898fed9203168a6f68218ecc._comment
new file mode 100644
index 000000000..c7d5802ff
--- /dev/null
+++ b/doc/todo/fsck_option_to_only_show_broken/comment_1_e42a2cfa898fed9203168a6f68218ecc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-10T12:21:37Z"
+ content="""
+Just use the `--quiet` option, then it will only show the errors (failed files/keys).
+"""]]

diff --git a/doc/todo/fsck_option_to_only_show_broken.mdwn b/doc/todo/fsck_option_to_only_show_broken.mdwn
new file mode 100644
index 000000000..cade432e4
--- /dev/null
+++ b/doc/todo/fsck_option_to_only_show_broken.mdwn
@@ -0,0 +1,3 @@
+`git annex fsck` currently spams the terminal with all keys in a repo and prints `git-annex: fsck: n failed` at the end if errors occur. Finding these errors in a sea of `ok`s is not trivial however.
+
+A simple solution to this could be an fsck option which skips printing ok'd (and perhaps also dead) keys, i.e. `--no-ok` and `--no-dead`.

diff --git a/doc/bugs/assistant_tries_to_drop_all_files_on_startup.mdwn b/doc/bugs/assistant_tries_to_drop_all_files_on_startup.mdwn
new file mode 100644
index 000000000..11f1cbd45
--- /dev/null
+++ b/doc/bugs/assistant_tries_to_drop_all_files_on_startup.mdwn
@@ -0,0 +1,53 @@
+### Please describe the problem.
+
+When running the assistant, it seems to want to drop all files in the worktree from my NAS which is in the transfer group. This fails because of numcopies thankfully but it strikes me as very odd and potentially dangerous for it to do this when it knows that it can't drop these files.
+
+It also unnecessarily spams the logs.
+
+### What steps will reproduce the problem?
+
+```
+git annex assistant --stop
+git annex assistant
+```
+
+### What version of git-annex are you using? On what operating system?
+
+```
+git-annex version: 8.20210428
+build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Feeds Testsuite S3 WebDAV
+dependency versions: aws-0.22 bloomfilter-2.0.1.0 cryptonite-0.28 DAV-1.3.4 feed-1.3.2.0 ghc-8.10.4 http-client-0.6.4.1 persistent-sqlite-2.11.1.0 torrent-10000.1.1 uuid-1.3.14 yesod-1.6.1.1
+key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
+remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
+operating system: linux x86_64
+supported repository versions: 8
+upgrade supported from repository versions: 0 1 2 3 4 5 6 7
+local repository version: 8
+```
+
+https://github.com/Atemu/nixpkgs/tree/498831397e77a265c240cf8f8a7d15e738f2f05b
+
+
+### Please provide any additional information below.
+
+The log is full of
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+drop SOTERIA path/to/file (unsafe) 
+  Could only verify the existence of 1 out of 2 necessary copies
+
+  Maybe add some of these git remotes (git remote add ...):
+  	d7d728f7-891a-4035-a758-c7ee80a8017a -- MB-<redacted>
+
+  (Use --force to override this check, or adjust numcopies.)
+failed
+# End of transcript or log.
+"""]]
+
+
+
+### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
+
+

diff --git a/doc/bugs/Git_repos_corrupt_themselves.mdwn b/doc/bugs/Git_repos_corrupt_themselves.mdwn
new file mode 100644
index 000000000..38376a813
--- /dev/null
+++ b/doc/bugs/Git_repos_corrupt_themselves.mdwn
@@ -0,0 +1,106 @@
+### Please describe the problem.
+
+This has happened a few times now which is why I'm reporting it. Git-annex seems to do something that causes my git repo to randomly corrupt on their own which is very worrying because I need to trust these repos to keep their content safe.
+It has never happened with regular repos and happens on both my Linux machine and my MBP. It hasn't happened on my NAS (SOTERIA) yet though which is exclusively accessed remotely, so I suspect this is an issue with the assistant/daemon.
+
+### What steps will reproduce the problem?
+
+Just have the assistant running, committing and syncing. No idea what other factors migh play into this.
+
+### What version of git-annex are you using? On what operating system?
+
+```
+git-annex version: 8.20210428
+build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Feeds Testsuite S3 WebDAV
+dependency versions: aws-0.22 bloomfilter-2.0.1.0 cryptonite-0.28 DAV-1.3.4 feed-1.3.2.0 ghc-8.10.4 http-client-0.6.4.1 persistent-sqlite-2.11.1.0 torrent-10000.1.1 uuid-1.3.14 yesod-1.6.1.1
+key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
+remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
+operating system: linux x86_64
+supported repository versions: 8
+upgrade supported from repository versions: 0 1 2 3 4 5 6 7
+local repository version: 8
+```
+
+https://github.com/Atemu/nixpkgs/tree/498831397e77a265c240cf8f8a7d15e738f2f05b
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+[2021-05-09 17:55:13.653645489] Committer: Committing changes to git
+(recording state in git...)
+[2021-05-09 17:55:13.702843262] Pusher: Syncing with SOTERIA 
+To ssh://192.168.101.24/~/Annex/Documents.git/
+   041f52d19..40cc59126  master -> synced/master
+git-annex: internal error: evacuate: strange closure type 4325399
+    (GHC version 8.10.4 for x86_64_unknown_linux)
+    Please report this as a GHC bug:  https://www.haskell.org/ghc/reportabug
+(recording state in git...)
+(scanning...) ControlSocket .git/annex/ssh/atemu@192.168.101.24 already exists, disabling multiplexing
+(started...) 
+(recording state in git...)
+Unpacking all pack files.
+remote: error: cannot lock ref 'refs/heads/synced/git-annex': is at 9166c83718695df3021d5bbf4fef2297d3f4cc84 but expected 7f761edbbe3c2a4710c629e9e7fdfb730c0639e7        
+remote: error: cannot lock ref 'refs/heads/synced/master': is at 42cab466f705c2496fb19249e272487bceb38808 but expected 40cc591261675e872f79b6a9ea966215d3f73581        
+To ssh://192.168.101.24/~/Annex/Documents.git/
+ ! [remote rejected]     git-annex -> synced/git-annex (failed to update ref)
+ ! [remote rejected]     master -> synced/master (failed to update ref)
+error: failed to push some refs to 'ssh://192.168.101.24/~/Annex/Documents.git/'
+To ssh://192.168.101.24/~/Annex/Documents.git/
+   7f761edbb..9166c8371  git-annex -> synced/git-annex
+   40cc59126..42cab466f  master -> synced/master
+fatal: early EOF
+git-annex: internal error: evacuate: strange closure type 4325399
+    (GHC version 8.10.4 for x86_64_unknown_linux)
+    Please report this as a GHC bug:  https://www.haskell.org/ghc/reportabug
+(recording state in git...)
+ControlSocket .git/annex/ssh/atemu@192.168.101.24 already exists, disabling multiplexing
+Auto packing the repository in background for optimum performance.
+See "git help gc" for manual housekeeping.
+error: Could not read 1f2ab777cdd4eb9add96d42de5022bde0a4a9a8b
+error: Could not read 0f74453f84ff23d31b00a9bc9c331c00988f465a
+error: Could not read 0f74453f84ff23d31b00a9bc9c331c00988f465a
+error: Could not read 1f2ab777cdd4eb9add96d42de5022bde0a4a9a8b
+error: Could not read 0f74453f84ff23d31b00a9bc9c331c00988f465a
+error: Could not read 1f2ab777cdd4eb9add96d42de5022bde0a4a9a8b
+error: Could not read 0f74453f84ff23d31b00a9bc9c331c00988f465a
+error: Could not read 1f2ab777cdd4eb9add96d42de5022bde0a4a9a8b
+error: Could not read 0f74453f84ff23d31b00a9bc9c331c00988f465a
+hint: Using 'master' as the name for the initial branch. This default branch name
+hint: is subject to change. To configure the initial branch name to use in all
+hint: of your new repositories, which will suppress this warning, call:
+hint: 
+hint: 	git config --global init.defaultBranch <name>
+hint: 
+hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
+hint: 'development'. The just-created branch can be renamed via this command:
+hint: 
+hint: 	git branch -m <name>
+Initialized empty Git repository in /tmp/tmpreporFb6Gq/.git/
+Trying to recover missing objects from remote SOTERIA.
+fatal: 'SOTERIA' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+Trying to recover missing objects from remote SOTERIA.
+fatal: 'SOTERIA' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+65 missing objects could not be recovered!
+To force a recovery to a usable state, retry with the --force parameter.
+# End of transcript or log.
+"""]]
+
+I'm not precisely sure when the actual crash happened (could be that it happened after starting up the machine today) as the log is a bit ambiguous. All I know is that it was corrupted today and that I was making commits till yesterday ~18:00.
+
+The objects mentioned in the log are both 6 days old; one is a commit on master and one on git-annex.
+
+Git fsck spat out a huge list of broken blobs and trees.
+
+### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
+
+There are a surprising amount of weird bugs and quirks like these but it's such an amazing tool, there's nothing like it.

user error, not a bug
diff --git a/doc/bugs/git_annex_merge_only_merges_synced_master_branch.mdwn b/doc/bugs/git_annex_merge_only_merges_synced_master_branch.mdwn
deleted file mode 100644
index 9ee66dcd2..000000000
--- a/doc/bugs/git_annex_merge_only_merges_synced_master_branch.mdwn
+++ /dev/null
@@ -1,4 +0,0 @@
-If I do git-annex sync remote when in branch foo, 
-and then in the remote repo, do git-annex merge,
-it does not merge the synced/foo branch, despite branch foo being checked
-out. --[[Joey]]

bug report
diff --git a/doc/bugs/git_annex_merge_only_merges_synced_master_branch.mdwn b/doc/bugs/git_annex_merge_only_merges_synced_master_branch.mdwn
new file mode 100644
index 000000000..9ee66dcd2
--- /dev/null
+++ b/doc/bugs/git_annex_merge_only_merges_synced_master_branch.mdwn
@@ -0,0 +1,4 @@
+If I do git-annex sync remote when in branch foo, 
+and then in the remote repo, do git-annex merge,
+it does not merge the synced/foo branch, despite branch foo being checked
+out. --[[Joey]]

Added a comment
diff --git a/doc/forum/Apple_M1_Silicon/comment_6_0fc6e261c00f1df8698c92c8de6f3a27._comment b/doc/forum/Apple_M1_Silicon/comment_6_0fc6e261c00f1df8698c92c8de6f3a27._comment
new file mode 100644
index 000000000..4d87f91e9
--- /dev/null
+++ b/doc/forum/Apple_M1_Silicon/comment_6_0fc6e261c00f1df8698c92c8de6f3a27._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="strmd"
+ avatar="http://cdn.libravatar.org/avatar/035707b9756129bbdea6b36a7f7b38d3"
+ subject="comment 6"
+ date="2021-05-07T20:00:07Z"
+ content="""
+Seeing some strange things lately, I believe it started after updating to macOS 11.3. Some git annex commands work fine (like `git annex àdd` or copying to a remote), others (like `git annex sync`, the webapp) throw errors like this:
+
+    git-annex(55965,0x2046f9e00) malloc: can't allocate region
+    :*** mach_vm_map(size=1048576, flags: 100) failed (error code=268435465)
+    git-annex(55965,0x2046f9e00) malloc: *** set a breakpoint in malloc_error_break to debug
+    git-annex: git: createProcess: runInteractiveProcess: exec: resource exhausted (Cannot allocate memory)
+
+I'm using `8.20210331-g1fb59a63a` from the .dmg provided here. I realize it's a bit of a hack setup so I haven't really investigated much yet, just wondering if someone knows what may be going on.
+"""]]

Added a comment: thanks
diff --git a/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_3_0ec752dbe8ef55a9884c1c5e83887505._comment b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_3_0ec752dbe8ef55a9884c1c5e83887505._comment
new file mode 100644
index 000000000..60c0c2084
--- /dev/null
+++ b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_3_0ec752dbe8ef55a9884c1c5e83887505._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="kyle"
+ avatar="http://cdn.libravatar.org/avatar/7d6e85cde1422ad60607c87fa87c63f3"
+ subject="thanks"
+ date="2021-05-07T18:07:24Z"
+ content="""
+Sounds great, thank you!
+"""]]

reinject: Error out when run on a file that is not annexed
rather than silently skipping it
diff --git a/CHANGELOG b/CHANGELOG
index 5a5772156..4f73fbcec 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,6 +8,8 @@ git-annex (8.20210429) UNRELEASED; urgency=medium
   * Fix behavior of several commands, including reinject, addurl, and rmurl
     when given an absolute path to an unlocked file, or a relative path
     that leaves and re-enters the repository.
+  * reinject: Error out when run on a file that is not annexed, rather
+    than silently skipping it.
 
  -- Joey Hess <id@joeyh.name>  Mon, 03 May 2021 10:33:10 -0400
 
diff --git a/Command/Reinject.hs b/Command/Reinject.hs
index c49b23400..a5ac6b1e3 100644
--- a/Command/Reinject.hs
+++ b/Command/Reinject.hs
@@ -44,7 +44,9 @@ startSrcDest :: [FilePath] -> CommandStart
 startSrcDest ps@(src:dest:[])
 	| src == dest = stop
 	| otherwise = notAnnexed src' $
-		ifAnnexed (toRawFilePath dest) go stop
+		ifAnnexed (toRawFilePath dest) 
+			go
+			(giveup $ src ++ " is not an annexed file")
   where
 	src' = toRawFilePath src
 	go key = starting "reinject" ai si $
diff --git a/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi.mdwn b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi.mdwn
index 93c26832a..adf1b4198 100644
--- a/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi.mdwn
+++ b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi.mdwn
@@ -39,3 +39,5 @@ configuration in the script above) or a relative path is used
 
 [[!meta author=kyle]]
 [[!tag projects/datalad]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_2_1b9b2ebc78949c7b39a255c291d11891._comment b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_2_1b9b2ebc78949c7b39a255c291d11891._comment
new file mode 100644
index 000000000..0db337caf
--- /dev/null
+++ b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_2_1b9b2ebc78949c7b39a255c291d11891._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2021-05-07T17:28:43Z"
+ content="""
+Fixed them all, and made reinject not skip over non-annexed files.
+"""]]

comment
diff --git a/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_1_10590563da0f80fa8326a90977966509._comment b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_1_10590563da0f80fa8326a90977966509._comment
new file mode 100644
index 000000000..ac33c842f
--- /dev/null
+++ b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi/comment_1_10590563da0f80fa8326a90977966509._comment
@@ -0,0 +1,37 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-07T15:57:03Z"
+ content="""
+It thinks the file is not annexed, due to asking git cat-file about it, and
+git cat-file not supporting paths that extend outside the repo.
+
+Most commands pass through ls-files which makes absolute relative.
+A similar bug has been fixed earlier for --batch with absolute
+filenames, [[!commit 957a87b437d6f056aa159e484a5f0a5af54e45db]].
+
+Also, `git-annex reinject /path/to/foo bar` fails to notice when the first
+parameter is an annexed file, for the same reason.
+
+And, grepping for ifAnnexed, whenAnnexed, and lookupKey, I found some
+other commands that also have the same problem, including rekey
+(also silently skips it), addurl --file (refuses to overwrite file, rather
+than adding url to key), rmurl (silently skips). Seems likely there are
+other commands with the bug too, that call those functions indirectly.
+
+Also, `git annex reinject content ../thisrepo/foo` fails in a really ugly
+way with a lot of "is outside repository" from git (despite it being
+inside the repository).
+
+So I think that it probably makes sense for catKeyFile to fix up the path
+to avoid these problems. There could be other problems caused by absolute
+paths, but at least that would eliminate this particular set of bugs.
+
+---
+
+This also raises the question of why reinject silently ignores non-annexed
+files. I don't think there's really a good reason, other than git-annex
+generally ignoring non-annexed files. But in this case, the user is
+explicitly providing the content of the file, so has a high
+expectation it's annexed.
+"""]]

patch review
diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_6_bd610770eff9ef1eb68085e28c1175fa._comment b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_6_bd610770eff9ef1eb68085e28c1175fa._comment
new file mode 100644
index 000000000..b2cc02ad8
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_6_bd610770eff9ef1eb68085e28c1175fa._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2021-05-07T15:28:34Z"
+ content="""
+misc-fixes merged
+"""]]
diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_7_f09b99a17d52a55e609bb3ca02db781a._comment b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_7_f09b99a17d52a55e609bb3ca02db781a._comment
new file mode 100644
index 000000000..3aa49e2c9
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_7_f09b99a17d52a55e609bb3ca02db781a._comment
@@ -0,0 +1,32 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 7"""
+ date="2021-05-07T15:28:46Z"
+ content="""
+The patch makes copyFileExternal slower on linux when CoW is not supported,
+as it will try cp --reflink=always every time, and then when it fails, 
+run cp a second time. This is why I discussed in my comment above that
+it would make sense to switch code using copyFileExternal to instead use
+tryCopyCoW.
+
+> GA couldn't handle reflink cp failing before AFAICT 
+
+Yes, it could, this is done in tryCopyCoW.
+
+> The reason I want it to be a configure flag is that some users might use
+> GA exclusively on non-APFS FSs (trying to reflink copy here would be a
+> waste of time)
+
+Current places that use tryCopyCoW maintain state, so it only
+pays the overhead of running cp one extra time to probe if reflinks work.
+That should also be possible on OSX. 
+
+I do not see a need for a build flag, also I doubt that many users in such
+a situation would rebuild with that flag.
+
+> some might prefer to use their $PATH's uutils-coreutils whose cp can
+> handle --reflink just like the GNU ones
+
+The system /bin/cp will always be there, right? So I don't see a need to
+bother about other cp implementations.
+"""]]

Added a comment: different keys for the same content
diff --git a/doc/todo/Hardlink_keys_with_same_hash_but_differrent_ext/comment_1_5af33851bdac4f34d83e8ef2e1d45355._comment b/doc/todo/Hardlink_keys_with_same_hash_but_differrent_ext/comment_1_5af33851bdac4f34d83e8ef2e1d45355._comment
new file mode 100644
index 000000000..3ad2e200f
--- /dev/null
+++ b/doc/todo/Hardlink_keys_with_same_hash_but_differrent_ext/comment_1_5af33851bdac4f34d83e8ef2e1d45355._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Ilya_Shlyakhter"
+ avatar="http://cdn.libravatar.org/avatar/1647044369aa7747829c38b9dcc84df0"
+ subject="different keys for the same content"
+ date="2021-05-07T15:37:46Z"
+ content="""
+Related: [[todo/alternate_keys_for_same_content]]
+"""]]

applied patch
diff --git a/doc/bugs/fromkey__58___create_directories_for_pointer_files__63__.mdwn b/doc/bugs/fromkey__58___create_directories_for_pointer_files__63__.mdwn
index 62cafdb62..dc3a70c7f 100644
--- a/doc/bugs/fromkey__58___create_directories_for_pointer_files__63__.mdwn
+++ b/doc/bugs/fromkey__58___create_directories_for_pointer_files__63__.mdwn
@@ -91,3 +91,6 @@ base-commit: dab2030702200bc9abea4bff9ce83ba63aeca41c
 
 [[!meta author=kyle]]
 [[!tag projects/datalad]]
+
+> Thanks for the patch, applied
+> [[done]] --[[Joey]]

reinject: silent failure with absolute path to pointer file
diff --git a/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi.mdwn b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi.mdwn
new file mode 100644
index 000000000..93c26832a
--- /dev/null
+++ b/doc/bugs/reinject__58___silent_failure_with_absolute_path_to_poi.mdwn
@@ -0,0 +1,41 @@
+When using `reinject <src> <dest>` and `dest` is an absolute path to a
+pointer file, the operation silently fails to reinject the content.
+
+[[!format sh """
+cd "$(mktemp -d "${TMPDIR:-/tmp}"/ga-XXXXXXX)" || exit 1
+
+git version
+git annex version | head -1
+
+git init -q
+git annex init
+git config annex.addunlocked true
+
+git annex fromkey --force \
+    SHA256E-s3--2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae \
+    foo
+
+printf foo >.git/tmp-to-copy
+git annex reinject .git/tmp-to-copy "$PWD"/foo
+echo $?
+cat foo
+"""]]
+
+```
+git version 2.31.1.705.g1ce651569c
+git-annex version: 8.20210429-g06e996efa
+init  (scanning for unlocked files...)
+ok
+(recording state in git...)
+fromkey foo ok
+(recording state in git...)
+0
+/annex/objects/SHA256E-s3--2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
+```
+
+If a link destination is used (i.e. drop the `addunlocked`
+configuration in the script above) or a relative path is used
+(i.e. drop the `"$PWD"/`), the content is injected.
+
+[[!meta author=kyle]]
+[[!tag projects/datalad]]

patch: fromkey: create directory for pointer files too
diff --git a/doc/bugs/fromkey__58___create_directories_for_pointer_files__63__.mdwn b/doc/bugs/fromkey__58___create_directories_for_pointer_files__63__.mdwn
new file mode 100644
index 000000000..62cafdb62
--- /dev/null
+++ b/doc/bugs/fromkey__58___create_directories_for_pointer_files__63__.mdwn
@@ -0,0 +1,93 @@
+Thanks for extending `fromkey` to support for unlocked files.  When
+updating some DataLad code to make use of this, a test flagged a
+difference between how links and pointer files are handled: the
+necessary leading directories will be created for links but not
+pointer files.
+
+[[!format sh """
+cd "$(mktemp -d "${TMPDIR:-/tmp}"/ga-XXXXXXX)" || exit 1
+
+git version
+git annex version | head -1
+
+git init -q
+git annex init
+
+set -x
+
+git annex fromkey --force \
+    SHA256E-s4--b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c \
+    foo/a
+git cat-file -p :foo/a
+
+git config annex.addunlocked true
+git annex fromkey --force \
+    SHA256E-s4--7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730 \
+    bar/a
+"""]]
+
+```
+git version 2.31.1.705.g1ce651569c
+git-annex version: 8.20210429-gdab203070
+init  (scanning for unlocked files...)
+ok
+(recording state in git...)
++ git annex fromkey --force SHA256E-s4--b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c foo/a
+fromkey foo/a ok
+(recording state in git...)
++ git cat-file -p :foo/a
+../.git/annex/objects/91/9x/SHA256E-s4--b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c/SHA256E-s4--b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c+ git config annex.addunlocked true
++ git annex fromkey --force SHA256E-s4--7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730 bar/a
+fromkey bar/a
+git-annex: bar/a: openBinaryFile: does not exist (No such file or directory)
+failed
+(recording state in git...)
+git-annex: fromkey: 1 failed
+```
+
+The caller can of course make sure that leading directories exist, but
+I think it makes sense for the locked and unlocked variants to behave
+the same here.  What do you think about the patch below?
+
+[[!format patch """
+From f6c97b8d01c7e9b8069638e9827062aa2462d429 Mon Sep 17 00:00:00 2001
+From: Kyle Meyer <kyle@kyleam.com>
+Date: Thu, 6 May 2021 11:11:14 -0400
+Subject: [PATCH] fromkey: create directory for pointer files too
+
+fromkey creates leading directories for symbolic links.  Do the same
+for pointer files.
+---
+ Command/FromKey.hs | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Command/FromKey.hs b/Command/FromKey.hs
+index eadb89fd1..16ff1693f 100644
+--- a/Command/FromKey.hs
++++ b/Command/FromKey.hs
+@@ -106,6 +106,7 @@ perform matcher key file = lookupKeyNotHidden file >>= \case
+ 					, matchKey = Just key
+ 					}
+ 				else keyMatchInfoWithoutContent key file
++			createWorkTreeDirectory (parentDir file)
+ 			ifM (addUnlocked matcher mi contentpresent)
+ 				( do
+ 					stagePointerFile file Nothing =<< hashPointerFile key
+@@ -115,7 +116,6 @@ perform matcher key file = lookupKeyNotHidden file >>= \case
+ 						else writepointer
+ 				, do
+ 					link <- calcRepo $ gitAnnexLink file key
+-					createWorkTreeDirectory (parentDir file)
+ 					addAnnexLink link file
+ 				)
+ 			next $ return True
+
+base-commit: dab2030702200bc9abea4bff9ce83ba63aeca41c
+-- 
+2.31.1.705.g1ce651569c
+
+"""]]
+
+
+[[!meta author=kyle]]
+[[!tag projects/datalad]]

Added a comment
diff --git a/doc/tips/Repositories_with_large_number_of_files/comment_9_c2b44076201d8152f16e12cb23c50397._comment b/doc/tips/Repositories_with_large_number_of_files/comment_9_c2b44076201d8152f16e12cb23c50397._comment
new file mode 100644
index 000000000..364832cc1
--- /dev/null
+++ b/doc/tips/Repositories_with_large_number_of_files/comment_9_c2b44076201d8152f16e12cb23c50397._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="pat"
+ avatar="http://cdn.libravatar.org/avatar/6b552550673a6a6df3b33364076f8ea8"
+ subject="comment 9"
+ date="2021-05-05T22:51:28Z"
+ content="""
+Separate branch is a no-go. `git annex info` takes 3 minutes 30 seconds to report 320k annex keys.
+
+So for my purposes I think I will keep one slow reference repo, and one fast working repo.
+"""]]

update
diff --git a/doc/thanks/list b/doc/thanks/list
index 82c395bdc..7e3217e50 100644
--- a/doc/thanks/list
+++ b/doc/thanks/list
@@ -112,3 +112,5 @@ Jarkko Kniivilä,
 Alex, 
 Dr. Land Raider, 
 Bence parhuzamos, 
+Nick White, 
+dukeofcool199, 

Added a comment
diff --git a/doc/tips/Repositories_with_large_number_of_files/comment_8_25a26f5210986655808992533aa48d3d._comment b/doc/tips/Repositories_with_large_number_of_files/comment_8_25a26f5210986655808992533aa48d3d._comment
new file mode 100644
index 000000000..ce124ab71
--- /dev/null
+++ b/doc/tips/Repositories_with_large_number_of_files/comment_8_25a26f5210986655808992533aa48d3d._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="pat"
+ avatar="http://cdn.libravatar.org/avatar/6b552550673a6a6df3b33364076f8ea8"
+ subject="comment 8"
+ date="2021-05-05T19:39:11Z"
+ content="""
+Do you have any information on actual times for working with big repos?
+
+As an example, I created one with 400k files. After following the steps here, `git status` takes 8 seconds to complete. I have plenty of resources. So, it's just slow. I am curious what sort of times you're getting with your big repos.
+
+I will have to see if submodules help with this at all. This material is all reference information, and isn't going to be changed very much. So it's possible I'd be better off with an \"active\" repo, and a \"reference\" repo (maybe connected by submodule, maybe not).
+
+Joey did make the suggestion of storing those sorts of files in a separate branch. I just did a test, and it appears that the limiting factor is in fact the number of files in the working tree. Deleting a lot of the files brought git back up to speed. So from a simplicity standpoint, I may want to have a `reference` branch with those files in it. And perhaps have two local clones of the repo - one `main` and one `reference` so I can explore and copy files from `reference` to `main` as needed.
+"""]]

diff --git a/doc/bugs/__34__rename__58___permission_denied__34__.mdwn b/doc/bugs/__34__rename__58___permission_denied__34__.mdwn
index 54a7dc15c..32a2734dc 100644
--- a/doc/bugs/__34__rename__58___permission_denied__34__.mdwn
+++ b/doc/bugs/__34__rename__58___permission_denied__34__.mdwn
@@ -1,3 +1,10 @@
+## I'm considering this a "false alarm", but leaving it around for others who may run into it
+
+It took a long time to add the files (50 minutes). When I did, and did a `git status`, the ones that failed due to "permission denied" just appeared as having not been added. I added them, and it worked fine. I have no reason to believe that my folder has gotten corrupted.
+
+So I don't personally think this needs fixing. But if anyone else out there runs into this issue, at least this page is here.
+
+
 ### Please describe the problem.
 
 When adding 400k files to a new annex, I get an error "rename: permission denied". It doesn't seem to be about file permissions (I have `chown`ed them), and it's inconsistent from run to run. So each time I try the import, different files may show the permission denied error.

Added a comment
diff --git a/doc/forum/avoiding_copies_across_mutiple_file_systems/comment_1_2ff3e4d2af575b27b14a0a936ad8c52f._comment b/doc/forum/avoiding_copies_across_mutiple_file_systems/comment_1_2ff3e4d2af575b27b14a0a936ad8c52f._comment
new file mode 100644
index 000000000..d642f3021
--- /dev/null
+++ b/doc/forum/avoiding_copies_across_mutiple_file_systems/comment_1_2ff3e4d2af575b27b14a0a936ad8c52f._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-05T18:08:49Z"
+ content="""
+Have I understood you correctly, you have a \"primary\" repository (with all data/keys present), accessible by the clients via NFS/cifs/whatever? And the clients(/\"experiments\") want to check out a specific version/branch from that repo?
+
+I think you have two alternatives to cloning it everywhere including all keys:
+
+a) Every client clones the git repo (and remove the \"origin\" remote to ensure that nothing flows back), creates a symlink from `.git/annex/objects` to `/path/to/primary/.git/annex/objects` and checks out whatever version/branch it wants. Easy.
+
+b) Every client uses the primary repo, but via its own worktree (See `git-worktree`). git-annex supports external worktrees, but I'm not sure what problems could arise in this particular setup. 
+"""]]

diff --git a/doc/forum/avoiding_copies_across_mutiple_file_systems.mdwn b/doc/forum/avoiding_copies_across_mutiple_file_systems.mdwn
new file mode 100644
index 000000000..605f53066
--- /dev/null
+++ b/doc/forum/avoiding_copies_across_mutiple_file_systems.mdwn
@@ -0,0 +1,13 @@
+I first mentioned this issue in a thread about 4 years ago (https://git-annex.branchable.com/forum/git-annex_across_two_filesystems/), and at time was encouraged to instead open a new thread.   Priorities changed, and I'm only now returning to the issue.
+
+The situation we have is as follows:    We have a large collection of boundary condition data used in our weather/climate model.    Individual "experiments" are run against specific versions of this data and we would like to minimize the total storage footprint as well as time spent copying data at the beginning of an experiment.      The clones for the experiments would always be used in a read-only manner.  New files would never be added through these repos.
+
+At first glance,   using git-annex with `git clone --shared` would seem to be a good solution.     Unfortunately these experiments span a large number (~10) of separate cross-mounted filesystems and would result ~90% of the experiments still duplicating data rather than sharing across a hardlink.
+
+A couple of partial solutions suggest themselves.   (1)  Put all of the clones on the same filesystem as the primary repo, and then create a symlink within each experiment back to the corresponding clone.   (2) Maintain a secondary (fully populated) clone on each filesystem and ensure that the experiment setup script clones from the proper secondary.
+
+Option (1) is viable, but would require some negotiations with the computing center to ensure that there is a single filesystem that gives appropriate privileges to all of our users.   Tedious, but probably not a showstopper.
+
+Option (2) sounds like an improvement over having 90% of the experiments duplicating data locally, except ... because the secondary clones would need to support any recent model configuration, the 10x duplication of "all" data could be much larger than the hundreds of copies of the smaller subsets needed by individual experiments.
+
+Perhaps the ideal solution would be some sort of special "clone" that uses symlinks back to the primary repository.    These special clones would be read only, and could even disable "dangerous" git actions that would allow adding/modifying files.   `git-new-workdir` hints that something like this might be possible, but it does not appear to play nicely with git-annex in any event.

diff --git a/doc/todo/Hardlink_keys_with_same_hash_but_differrent_ext.mdwn b/doc/todo/Hardlink_keys_with_same_hash_but_differrent_ext.mdwn
new file mode 100644
index 000000000..c54e0e058
--- /dev/null
+++ b/doc/todo/Hardlink_keys_with_same_hash_but_differrent_ext.mdwn
@@ -0,0 +1,13 @@
+Currently, SHA256E creates duplicate files for different extensions, i.e.:
+
+```
+$ l * && l -Li * && sha256sum *
+lrwxrwxrwx 1 atemu users 198 2021-05-04 03:47 random.1 -> .git/annex/objects/F9/Kk/SHA256E-s104857600--2fdbdc9c3b23d1986a743aede593765e57ade9f173f9fd9766057f0efd63197a.1/SHA256E-s104857600--2fdbdc9c3b23d1986a743aede593765e57ade9f173f9fd9766057f0efd63197a.1
+lrwxrwxrwx 1 atemu users 198 2021-05-05 10:01 random.2 -> .git/annex/objects/Pm/J1/SHA256E-s104857600--2fdbdc9c3b23d1986a743aede593765e57ade9f173f9fd9766057f0efd63197a.2/SHA256E-s104857600--2fdbdc9c3b23d1986a743aede593765e57ade9f173f9fd9766057f0efd63197a.2
+ 3720 -r--r--r-- 1 atemu users 100M 2021-05-04 03:47 random.1
+49696 -r--r--r-- 1 atemu users 100M 2021-05-05 10:01 random.2
+2fdbdc9c3b23d1986a743aede593765e57ade9f173f9fd9766057f0efd63197a  random.1
+2fdbdc9c3b23d1986a743aede593765e57ade9f173f9fd9766057f0efd63197a  random.2
+```
+
+These have the exact same content though, they could be hardlinks of one another instead and nothing would change.

Added a comment
diff --git a/doc/forum/Make_GA_aware_of_externally-made_copies/comment_4_b0d7ef111f4862d6b759cde45696a676._comment b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_4_b0d7ef111f4862d6b759cde45696a676._comment
new file mode 100644
index 000000000..478bcf6f0
--- /dev/null
+++ b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_4_b0d7ef111f4862d6b759cde45696a676._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 4"
+ date="2021-05-05T07:33:07Z"
+ content="""
+It worked! Thank you so much you two!
+
+The cipher was indeed different for some reason, what could cause that?
+"""]]

diff --git a/doc/todo/Use_editorconfig_for_formatting_rules.mdwn b/doc/todo/Use_editorconfig_for_formatting_rules.mdwn
new file mode 100644
index 000000000..06bb32080
--- /dev/null
+++ b/doc/todo/Use_editorconfig_for_formatting_rules.mdwn
@@ -0,0 +1,3 @@
+https://editorconfig.org/ is a cross-editor standard for setting formatting rules like indent etc.
+
+A blurb of elisp probably isn't too useful to vim users and I had some really strange memory leak with it in my Emacs.

Added a comment
diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_5_4580926755ee2802c80baa9f9bcc0661._comment b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_5_4580926755ee2802c80baa9f9bcc0661._comment
new file mode 100644
index 000000000..9aad31075
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_5_4580926755ee2802c80baa9f9bcc0661._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 5"
+ date="2021-05-05T06:04:49Z"
+ content="""
+I've also got some small fixes for things that came up during development:
+
+https://github.com/Atemu/git-annex/tree/misc-fixes
+"""]]

Added a comment
diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_4_8fbd3cdc5a077cbd51d41db30c19a005._comment b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_4_8fbd3cdc5a077cbd51d41db30c19a005._comment
new file mode 100644
index 000000000..5e0f5feb4
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_4_8fbd3cdc5a077cbd51d41db30c19a005._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 4"
+ date="2021-05-05T05:43:56Z"
+ content="""
+https://github.com/Atemu/git-annex/tree/feature/macOS-reflinks
+"""]]

diff --git a/doc/bugs/__34__rename__58___permission_denied__34__.mdwn b/doc/bugs/__34__rename__58___permission_denied__34__.mdwn
new file mode 100644
index 000000000..54a7dc15c
--- /dev/null
+++ b/doc/bugs/__34__rename__58___permission_denied__34__.mdwn
@@ -0,0 +1,62 @@
+### Please describe the problem.
+
+When adding 400k files to a new annex, I get an error "rename: permission denied". It doesn't seem to be about file permissions (I have `chown`ed them), and it's inconsistent from run to run. So each time I try the import, different files may show the permission denied error.
+
+One thing I'm concerned about is how to confirm whether these files have made it into annex, or if I now have a corrupted folder structure.
+
+I do intend to do smaller imports, or try using `-J1`.
+
+
+### What steps will reproduce the problem?
+
+1. `git config annex.jobs cpus`
+2. `git annex add .`
+
+
+### What version of git-annex are you using? On what operating system?
+
+macOS 10.15.7
+
+```
+git-annex version: 8.20210310
+build flags: Assistant Webapp Pairing FsEvents TorrentParser MagicMime Feeds Testsuite S3 WebDAV
+dependency versions: aws-0.22 bloomfilter-2.0.1.0 cryptonite-0.28 DAV-1.3.4 feed-1.3.0.1 ghc-8.10.4 http-client-0.7.6 persistent-sqlite-2.11.1.0 torrent-10000.1.1 uuid-1.3.14 yesod-1.6.1.0
+key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
+remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
+operating system: darwin x86_64
+supported repository versions: 8
+upgrade supported from repository versions: 0 1 2 3 4 5 6 7
+```
+
+
+### Please provide any additional information below.
+
+iMac 10-core i9 (maybe 20 threads?)
+
+```
+git-annex: .git/annex/othertmp/ingest-A23998-2216: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-Ad23998-21291: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-P23998-30359: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-Audio23998-182890: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-wasd_clap_sys100_cra23998-206554: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-wasd_clap_sys100_f23998-206560: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-wasd_clap_sys100_f23998-206561: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-Fairligh23998-248968: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-ly23998-268165: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-123998-269213: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-46223998-278087.wav: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ing23998-290478: rename: permission denied (Permission denied)
+git-annex: .git/annex/othertmp/ingest-H23998-292758: rename: permission denied (Permission denied)
+```
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+
+# End of transcript or log.
+"""]]
+
+### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
+
+Absolutely! :)

git-commit pathspec change due to 424bef6b6
diff --git a/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn b/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn
new file mode 100644
index 000000000..862bb1fc8
--- /dev/null
+++ b/doc/bugs/case_where_using_pathspec_with_git-commit_leaves_s.mdwn
@@ -0,0 +1,117 @@
+424bef6b6 (smudge: check for known annexed inodes before checking
+annex.largefiles, 2021-05-03) fixed a case where an unlocked annexed
+file that annex.largefiles does not match could get its unchanged
+content checked into git.  This was in response to
+<https://git-annex.branchable.com/forum/one-off_unlocked_annex_files_that_go_against_large/>.
+
+In a comment there, Joey said:
+
+> I've made a change that seems to work, and will probably not break
+> other cases, although this is a complex and subtle area.
+
+I'm following up with a change in behavior flagged by a DataLad test.
+As with most things in this area, I have a hard time reasoning about
+what the expected behavior should be and whether it should be
+considered a bug.  Here's the reproducer:
+
+[[!format sh """
+set -eu
+
+cd "$(mktemp -d "${TMPDIR:-/tmp}"/ga-XXXXXXX)"
+
+git version
+git annex version | head -1
+
+git init -q
+git annex init
+
+echo a >foo
+git annex add foo
+git commit --quiet -m 'add foo'
+
+git annex unlock foo
+printf '* annex.largefiles=nothing\n' >.gitattributes
+
+sleep 1
+
+git annex add foo
+git commit -q -m 'commit unlocked' -- foo
+
+set -x
+export PS4='> '
+git diff HEAD^- -- foo
+git diff --cached
+"""]]
+
+Here's the output with 8.20210428:
+
+```
+git version 2.31.1.659.g12c5fe8677
+git-annex version: 8.20210428
+[...]
+> git diff HEAD^- -- foo
+diff --git a/foo b/foo
+deleted file mode 120000
+index 8a2a0c9..0000000
+--- a/foo
++++ /dev/null
+@@ -1 +0,0 @@
+-.git/annex/objects/3z/F8/SHA256E-s2--87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7/SHA256E-s2--87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
+\ No newline at end of file
+diff --git a/foo b/foo
+new file mode 100644
+index 0000000..7898192
+--- /dev/null
++++ b/foo
+@@ -0,0 +1 @@
++a
+> git diff --cached
+```
+
+And here's the output with a recent commit on master following
+424bef6b6:
+
+```
+git version 2.31.1.659.g12c5fe8677
+git-annex version: 8.20210429-ge811a50e2
+[...]
+> git diff HEAD^- -- foo
+diff --git a/foo b/foo
+deleted file mode 120000
+index 8a2a0c9..0000000
+--- a/foo
++++ /dev/null
+@@ -1 +0,0 @@
+-.git/annex/objects/3z/F8/SHA256E-s2--87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7/SHA256E-s2--87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
+\ No newline at end of file
+diff --git a/foo b/foo
+new file mode 100644
+index 0000000..3de500c
+--- /dev/null
++++ b/foo
+@@ -0,0 +1 @@
++/annex/objects/SHA256E-s2--87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
+> git diff --cached
+diff --git a/foo b/foo
+index 3de500c..7898192 100644
+--- a/foo
++++ b/foo
+@@ -1 +1 @@
+-/annex/objects/SHA256E-s2--87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
++a
+```
+
+Before 424bef6b6, `git annex add foo + git commit ... foo` results in
+a commit that has foo's content tracked in git.  After 424bef6b6, the
+unlocked file is still recorded, and the switch to being tracked by
+git ends up staged in the index.
+
+The new behavior isn't seen if the pathspec is dropped from `git
+commit`.  Also, without the sleep, it isn't triggered reliably
+(presumably because the index and foo have the same mtime, bypassing
+the clean filter).
+
+Thanks for taking a look.
+
+[[!meta author=kyle]]
+[[!tag projects/datalad]]

Added a comment
diff --git a/doc/forum/Apple_M1_Silicon/comment_5_2efc89b2c4f3ff408ccd015f297d743b._comment b/doc/forum/Apple_M1_Silicon/comment_5_2efc89b2c4f3ff408ccd015f297d743b._comment
new file mode 100644
index 000000000..b25256809
--- /dev/null
+++ b/doc/forum/Apple_M1_Silicon/comment_5_2efc89b2c4f3ff408ccd015f297d743b._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="cecile.madjar@d95f9e618c3dff4829e7fedba1a71e1499542f3f"
+ nickname="cecile.madjar"
+ avatar="http://cdn.libravatar.org/avatar/a32ab97180285c0e5095bad4616a4d87"
+ subject="comment 5"
+ date="2021-05-04T21:12:52Z"
+ content="""
+Thank you Lukey. Indeed, after installing Rosetta2 it worked. Thank you!
+"""]]

Added a comment
diff --git a/doc/forum/Apple_M1_Silicon/comment_4_07c410bacefa5da582ce2064ef345def._comment b/doc/forum/Apple_M1_Silicon/comment_4_07c410bacefa5da582ce2064ef345def._comment
new file mode 100644
index 000000000..5c327a061
--- /dev/null
+++ b/doc/forum/Apple_M1_Silicon/comment_4_07c410bacefa5da582ce2064ef345def._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 4"
+ date="2021-05-04T20:38:01Z"
+ content="""
+Hmm, shouldn't it work just fine with rosetta?
+"""]]

Added a comment
diff --git a/doc/forum/Help_with_git-annex_and_controlmaster/comment_4_51312d1662d0794e4258551c59877434._comment b/doc/forum/Help_with_git-annex_and_controlmaster/comment_4_51312d1662d0794e4258551c59877434._comment
new file mode 100644
index 000000000..20710c249
--- /dev/null
+++ b/doc/forum/Help_with_git-annex_and_controlmaster/comment_4_51312d1662d0794e4258551c59877434._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 4"
+ date="2021-05-04T20:31:45Z"
+ content="""
+Even with concurrency enabled, this should not be a problem in your case, as you're manually doing the controlmaster setup.
+
+@joey I guess there needs to be a way to hide such messages, like git with the `advice.*` configuration options.
+"""]]

Added a comment
diff --git a/doc/forum/Apple_M1_Silicon/comment_3_bed7d9e5565c6bb462e2ba8f4d815725._comment b/doc/forum/Apple_M1_Silicon/comment_3_bed7d9e5565c6bb462e2ba8f4d815725._comment
new file mode 100644
index 000000000..06db6f151
--- /dev/null
+++ b/doc/forum/Apple_M1_Silicon/comment_3_bed7d9e5565c6bb462e2ba8f4d815725._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="cecile.madjar@d95f9e618c3dff4829e7fedba1a71e1499542f3f"
+ nickname="cecile.madjar"
+ avatar="http://cdn.libravatar.org/avatar/a32ab97180285c0e5095bad4616a4d87"
+ subject="comment 3"
+ date="2021-05-04T20:24:50Z"
+ content="""
+Hello,
+
+Is there any updates on this? I am using an Apple M1 Silicon and I am blocked in all my projects because I cannot install git-annex on my computer. Do you have an approximate idea of when this would be available for Apple M1 Silicon users?
+
+Thank you,
+
+
+"""]]

removed
diff --git a/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_3_5670165fdc048e434bdd30c8a27a1f72._comment b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_3_5670165fdc048e434bdd30c8a27a1f72._comment
deleted file mode 100644
index b681a4a98..000000000
--- a/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_3_5670165fdc048e434bdd30c8a27a1f72._comment
+++ /dev/null
@@ -1,10 +0,0 @@
-[[!comment format=mdwn
- username="yarikoptic"
- avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
- subject="comment 3"
- date="2021-05-04T17:51:09Z"
- content="""
-> It also seems to me that, if you're splitting a repo, you would also want to include things like trust.log and remote.log, or at least parts of them for some remotes?
-
-yes. Even if not splitting but just copying a key (or multiple keys) since might need special remote configuration etc.
-"""]]

Added a comment
diff --git a/doc/forum/Help_with_git-annex_and_controlmaster/comment_3_4fe0973f6b7f912e2e4163ebf5dfc5d4._comment b/doc/forum/Help_with_git-annex_and_controlmaster/comment_3_4fe0973f6b7f912e2e4163ebf5dfc5d4._comment
new file mode 100644
index 000000000..b591afd08
--- /dev/null
+++ b/doc/forum/Help_with_git-annex_and_controlmaster/comment_3_4fe0973f6b7f912e2e4163ebf5dfc5d4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="fortran"
+ avatar="http://cdn.libravatar.org/avatar/ee27e12e945c0af698d58f0d8dde2457"
+ subject="comment 3"
+ date="2021-05-04T19:25:47Z"
+ content="""
+Essentially, we are hoping to deploy git-annex so the less messages from git-annex, the better for our end users. (Or, I guess, my *supporting* the end users :) )
+"""]]

Added a comment
diff --git a/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_5e57d563d351cc8c850c9cc4726ad23b._comment b/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_5e57d563d351cc8c850c9cc4726ad23b._comment
new file mode 100644
index 000000000..98a73b47c
--- /dev/null
+++ b/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_5e57d563d351cc8c850c9cc4726ad23b._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="fortran"
+ avatar="http://cdn.libravatar.org/avatar/ee27e12e945c0af698d58f0d8dde2457"
+ subject="comment 2"
+ date="2021-05-04T19:10:35Z"
+ content="""
+Oh. Wow. That's a big man page...
+
+Okay. So if I run `git config annex.sshcaching false`, then things are happier. Well:
+
+```
+❯ git annex get file1.nc4
+get file1.nc4 (from origin...)
+
+  You have enabled concurrency, but git-annex is not able to use ssh connection caching. This may result in multiple ssh processes prompting for passwords at the same time.
+
+  annex.sshcaching is not set to true
+ok
+(recording state in git...)
+```
+
+Now, reading the man pages, I see that the default concurrency is 1, so I think I'm safe?  Or is there perhaps something I should use to tell it \"nope\" for that?
+"""]]

Added a comment
diff --git a/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_3_5670165fdc048e434bdd30c8a27a1f72._comment b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_3_5670165fdc048e434bdd30c8a27a1f72._comment
new file mode 100644
index 000000000..b681a4a98
--- /dev/null
+++ b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_3_5670165fdc048e434bdd30c8a27a1f72._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 3"
+ date="2021-05-04T17:51:09Z"
+ content="""
+> It also seems to me that, if you're splitting a repo, you would also want to include things like trust.log and remote.log, or at least parts of them for some remotes?
+
+yes. Even if not splitting but just copying a key (or multiple keys) since might need special remote configuration etc.
+"""]]

Added a comment
diff --git a/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_2_8993cf9badc8348604c662e35ba6f199._comment b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_2_8993cf9badc8348604c662e35ba6f199._comment
new file mode 100644
index 000000000..e3c833654
--- /dev/null
+++ b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_2_8993cf9badc8348604c662e35ba6f199._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 2"
+ date="2021-05-04T17:50:45Z"
+ content="""
+> It also seems to me that, if you're splitting a repo, you would also want to include things like trust.log and remote.log, or at least parts of them for some remotes?
+
+yes. Even if not splitting but just copying a key (or multiple keys) since might need special remote configuration etc.
+"""]]

Added a comment
diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_3_d812c6dbd672e3dcdeb5c87806dcef91._comment b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_3_d812c6dbd672e3dcdeb5c87806dcef91._comment
new file mode 100644
index 000000000..a62f1cac0
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_3_d812c6dbd672e3dcdeb5c87806dcef91._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 3"
+ date="2021-05-04T17:37:04Z"
+ content="""
+Oh, I've already got all of that implemented; it's just the flag for disabling that behaviour at build time that's missing.
+
+What I did is to conditionally set the executable to `/bin/cp` and the reflink param to `-c`.
+
+The problem with using it without a fallback is that when you use it on a FS that doesn't support CoW, `/bin/cp` will hard-fail and make unlocking impossible. GNU coreutils actually fall back automatically by themselves, GA couldn't handle reflink cp failing before AFAICT. I refactored the copy functions a bit to make it fall back properly.
+
+The reason I want it to be a configure flag is that some users might use GA exclusively on non-APFS FSs (trying to reflink copy here would be a waste of time) and some might prefer to use their $PATH's uutils-coreutils whose `cp` can handle `--reflink` just like the GNU ones.
+
+~~I originally wanted to add it as a cabal configure flag but apparently you can't reference those anywhere?~~ Found this: https://stackoverflow.com/questions/48157516/conditional-compilation-in-haskell-submodule, that's probably what I'll end up doing. Will default to true on macOS.
+"""]]

Added a comment
diff --git a/doc/forum/Make_GA_aware_of_externally-made_copies/comment_3_c1d69396c7bb208b6f82f2f65a282cfb._comment b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_3_c1d69396c7bb208b6f82f2f65a282cfb._comment
new file mode 100644
index 000000000..369552eae
--- /dev/null
+++ b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_3_c1d69396c7bb208b6f82f2f65a282cfb._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 3"
+ date="2021-05-04T17:19:57Z"
+ content="""
+I used the exact same settings for the second special remote as the first one: `type=directory chunk=50MiB encryption=hybrid mac=HMACSHA256`.
+
+GA was 8.20200810 though because my server machine is built from the stable Nixpkgs channel; I will test that again with the most recent version tomorrow.
+
+`--sameas` won't help here; the special remotes are accessible via the same FS (the second is just a btrfs snapshot of the first) and they'd still only count as one copy. That's the same situation I have right now.
+
+Counting it as two copies would work but there is a large delay between having moved the files to the special remote and them actually being mirrored (residential internet upload) which means the numcopies of somewhat newly added files wouldn't be correct. It'd be a step up though.
+"""]]

Added a comment
diff --git a/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__/comment_2_0d1e17e92d6022552406fef144e8c104._comment b/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__/comment_2_0d1e17e92d6022552406fef144e8c104._comment
new file mode 100644
index 000000000..b14fa55db
--- /dev/null
+++ b/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__/comment_2_0d1e17e92d6022552406fef144e8c104._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="yarikoptic"
+ avatar="http://cdn.libravatar.org/avatar/f11e9c84cb18d26a1748c33b48c924b4"
+ subject="comment 2"
+ date="2021-05-04T16:53:18Z"
+ content="""
+FWIW, verified that `git annex --debug initremote --sameas web datalad externaltype=datalad type=external encryption=none autoenable=true` makes `git-annex` to make `datalad` special remote to handle those urls.  And since we do not have any prioritization handling in datalad we also grab the first one (the api. one) returned by git-annex and proceed with it.
+
+So, indeed, if you do not like (or even just feel lukewarm) about an idea of adding costs within built-in `web` remote, feel welcome to close, and we will still have a way forward by providing such handling within datalad external special remote. It would be a bit sub-optimal since would require people to install datalad, but at least it would enable desired prioritization in some use cases (e.g. for QA `annex fsck --fast` run).
+
+And indeed with the singular cost (not even a range of costs) assigned/returned by a remote and no e.g. cost provisioned to be returned by CLAIMURL, I guess there is no (easy) way to mix-in the URL based costs into overall decision making to order the remotes.
+
+NB with `--sameas` trick above, `git-annex` doesn't even ask `datalad` with CLAIMURL and immediately passes `TRANSFER` of the key to `datalad` external remote.  Without `--sameas` - `git-annex` (8.20210330-g0b03b3d) doesn't even bother asking datalad (within `whereis` at least) on either it could CLAIMURL those... even if I assign `annex-cost = 1.0` for datalad remote.  Not sure yet if that is \"by design\".
+
+> When it gets down to the web remote, it tries the urls in whatever order it happens to have them.
+
+FWIW - I think I have tried to add them in different orders but it always went for the `api` one so I concluded that the order it has them is sorted and there is no way to \"tune it up\".
+
+P.S. I still wonder why I have some memory of git-annex supporting some (external) way to prioritize URLs... may be it was indeed \"craft a special remote to do that\"...
+"""]]

comment
diff --git a/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_1_68c86b06b3b0c8cc9c3faac97e3f6c3f._comment b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_1_68c86b06b3b0c8cc9c3faac97e3f6c3f._comment
new file mode 100644
index 000000000..8cd9485a9
--- /dev/null
+++ b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info/comment_1_68c86b06b3b0c8cc9c3faac97e3f6c3f._comment
@@ -0,0 +1,27 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-04T14:58:17Z"
+ content="""
+If I understand correctly, this might be as straightforard as extracting
+the various per-key logs from the git-annex branch, and shoving them into a
+new git tree, which the user can then do whatever with. Something like:
+
+	git-annex copy-key path/
+	8e1c53342eb6461eedf13ee7d15038b400c70269
+
+The obvious thing for the user to do with such a tree would be 
+to git push it to the other repo with a name ending in /git-annex,
+which git-annex there will then auto-merge into that repo's git-annex
+branch.
+
+When you start talking about hidden repos though, things get more complex,
+because exporting key logs from a hidden repo would necessarily expose the
+uuid of that repo, and maybe other logged information that was only
+stored in the hidden repo as well. If it has to filter it to only the parts
+of logs that are used by non-hidden repos, that would be a lot more complex.
+
+It also seems to me that, if you're splitting a repo, you would also want
+to include things like trust.log and remote.log, or at least parts of them
+for some remotes?
+"""]]

comment
diff --git a/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__/comment_1_55652562111e83129eb19a61da14ee4a._comment b/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__/comment_1_55652562111e83129eb19a61da14ee4a._comment
new file mode 100644
index 000000000..9684ac00b
--- /dev/null
+++ b/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__/comment_1_55652562111e83129eb19a61da14ee4a._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-05-04T14:33:42Z"
+ content="""
+Costs are information about the connection from the local repository to a
+remote, which is why they are stored only locally in the git config -- I
+may have much different cost than you to access the same repository.
+
+When there are multiple urls all claimed by the web remote, that's a
+single remote, and the code that looks at costs decides which remote is
+lowest cost, and tries that one first. When it gets down to the web remote,
+it tries the urls in whatever order it happens to have them.
+
+So, the proposed way to assign costs to urls could only change the order
+that urls are presented to the web remote. It would not let git-annex
+try to get first from web (cheap url), followed by another repo, followed
+by web (expensive url).
+
+What you can do is have a special remote, that claims all the relevent
+urls and then does its own ordering of them. Or perhaps different
+special remotes that claim different sets of urls, and assign costs to
+those remotes. (Using --sameas so the several remotes do not
+count as more than 1 copy.)
+"""]]

response
diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_2_e506d7b173bd04ad7f32db52dcc1ea03._comment b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_2_e506d7b173bd04ad7f32db52dcc1ea03._comment
new file mode 100644
index 000000000..31780a3a1
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_2_e506d7b173bd04ad7f32db52dcc1ea03._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2021-05-04T14:15:38Z"
+ content="""
+The cp command not falling back is ok, as long as it exits nonzero in a
+situation where it can't make a CoW copy and doesn't misbehave badly. In
+Annex/CopyFile.hs, tryCopyCoW probes to see if cp can make a CoW copy, and
+if not it falls back to copying itself, without cp.
+
+So what you can do is change copyCow in Utility/CopyFile.hs to support the
+OSX cp command and parameters (inside a `#ifdef darwin_HOST_OS`).
+
+Notice that the probe deals with discarding error messages from the
+command, also also deals with linux's cp failing after creating an empty
+file when it doesn't support CoW.
+
+That would leave copyFileExternal not using CoW; it could be made to probe
+too on OSX, but that's not really used in many places and it would probably
+make more sense to convert any of those places that matter to use
+Annex/CopyFile.hs's tryCopyCoW. This could be deferred until later.
+
+I don't think it needs to be a configure flag unless this feature is
+somehow flakey.
+"""]]

comment and todo
diff --git a/doc/forum/Make_GA_aware_of_externally-made_copies/comment_2_b7fcfd87efb17d5159ec49eb218fbd8e._comment b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_2_b7fcfd87efb17d5159ec49eb218fbd8e._comment
new file mode 100644
index 000000000..665cc13c2
--- /dev/null
+++ b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_2_b7fcfd87efb17d5159ec49eb218fbd8e._comment
@@ -0,0 +1,32 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2021-05-04T13:54:45Z"
+ content="""
+I think it should be possible to get this to work with chunking, if you
+have git-annex version 8.20201103 or newer, and if you configure the second
+special remote with the same chunk size.
+
+git-annex records state about a special remote's chunks, and that state is
+not available for the second special remote. Which used to prevent accessing
+chunks when the information is not available, but that version made it fall
+back to trying chunks of the configured chunk size.
+
+See the bug report that resulted in that change for details:
+[[bugs/fsck_--key_without___34__chunking__34___information_in_git-annex_does_not_try_chunks]]
+
+Oh also this only works with keys that have a recorded size. Which is most
+of them, but git-annex addurl --fast adds keys without a recorded size.
+
+---
+
+An alternative you might consider is to use the --sameas flag to initremote
+when setting up the second remote. Then git-annex would consider the two
+remotes as one repository, which means it only considers them to be one
+copy, but also it can retrieve content from either.
+
+If git-annex only had a way to treat a repository a more than 1 copy, that
+would do just what you want. I do think there might be the possibility to
+add such a feature, but it would need some thought.
+[[todo/repositories_that_count_as_more_than_one_copy]]
+"""]]
diff --git a/doc/todo/repositories_that_count_as_more_than_one_copy.mdwn b/doc/todo/repositories_that_count_as_more_than_one_copy.mdwn
new file mode 100644
index 000000000..8fcc87d6e
--- /dev/null
+++ b/doc/todo/repositories_that_count_as_more_than_one_copy.mdwn
@@ -0,0 +1,9 @@
+It may be useful for a repository to count as more than 1 copy of a file.
+
+Examples could include: A repository on S3, when a bucket is configured to be
+sufficiently durable. A --sameas special remote that accesses data copied
+from the other remote to another storage media (eg by a backup process).
+A repository on a RAID array.
+
+If this were made configurable, it might also make sense to allow a
+repository to count as less than 1 copy, eg 0.5 copies.

remove my comment as someone else already answered it well
diff --git a/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_77b488c0b3f7ec9027af58c2685192e9._comment b/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_77b488c0b3f7ec9027af58c2685192e9._comment
deleted file mode 100644
index 8c6389f4b..000000000
--- a/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_77b488c0b3f7ec9027af58c2685192e9._comment
+++ /dev/null
@@ -1,11 +0,0 @@
-[[!comment format=mdwn
- username="joey"
- subject="""comment 2"""
- date="2021-05-04T13:51:01Z"
- content="""
-You want: git config annex.sshcaching false
-
-This behavior is because git-annex uses ControlMaster itself as it
-sometimes needs multiple connections to a ssh host and most people don't
-have it set up.
-"""]]

response
diff --git a/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_77b488c0b3f7ec9027af58c2685192e9._comment b/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_77b488c0b3f7ec9027af58c2685192e9._comment
new file mode 100644
index 000000000..8c6389f4b
--- /dev/null
+++ b/doc/forum/Help_with_git-annex_and_controlmaster/comment_2_77b488c0b3f7ec9027af58c2685192e9._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2021-05-04T13:51:01Z"
+ content="""
+You want: git config annex.sshcaching false
+
+This behavior is because git-annex uses ControlMaster itself as it
+sometimes needs multiple connections to a ssh host and most people don't
+have it set up.
+"""]]

Added a comment
diff --git a/doc/forum/Help_with_git-annex_and_controlmaster/comment_1_2742e65d9faebab80bc5fa0877ef7d29._comment b/doc/forum/Help_with_git-annex_and_controlmaster/comment_1_2742e65d9faebab80bc5fa0877ef7d29._comment
new file mode 100644
index 000000000..b3707f359
--- /dev/null
+++ b/doc/forum/Help_with_git-annex_and_controlmaster/comment_1_2742e65d9faebab80bc5fa0877ef7d29._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-04T13:42:34Z"
+ content="""
+Hi, I think you have to set the `annex.sshcaching` config to `false`, since git-annex starts it's own controlmaster with that option. These options are documented in the [[git-annex]] manpage.
+"""]]

diff --git a/doc/forum/Help_with_git-annex_and_controlmaster.mdwn b/doc/forum/Help_with_git-annex_and_controlmaster.mdwn
new file mode 100644
index 000000000..1eebed380
--- /dev/null
+++ b/doc/forum/Help_with_git-annex_and_controlmaster.mdwn
@@ -0,0 +1,42 @@
+All,
+
+I am quite new to `git-annex` so it's possible/probable this is a FAQ, but my search-fu has failed me.
+
+Namely, I'm testing out `git-annex` and have a sample repo on a remote server, let's call it "foo". Now I have SSH Controlmaster setup because foo has both a password and PIN that need entered so I usually do a `screen` and run `ssh -MN foo` and detach so that I can do `ssh foo` and boom, on foo no problem. And I can do `scp foo:file .` and no need to enter in either.
+
+So then I tried following the walkthroughs here. First:
+
+```
+❯ git clone git+ssh://foo:/path/to/my/annex
+Cloning into 'annex'...
+remote: Enumerating objects: 28, done.
+remote: Counting objects: 100% (28/28), done.
+remote: Compressing objects: 100% (22/22), done.
+remote: Total 28 (delta 4), reused 0 (delta 0), pack-reused 0
+Receiving objects: 100% (28/28), done.
+Resolving deltas: 100% (4/4), done.
+```
+
+Nice. Then I did:
+
+```
+❯ git annex init "my laptop"
+init my laptop (scanning for unlocked files...)
+Enter PIN:
+Password:
+ok
+(recording state in git...)
+```
+
+Worked, but had to enter PIN and password. And then I `get` and:
+
+```
+❯ git annex get file1.nc4
+get file1.nc4 (from origin...)
+Enter PIN:
+Password:
+ok
+(recording state in git...)
+```
+
+Same thing: worked, but had to do PIN/password. So, is there a way I can utilize an existing controlmaster "tunnel" and avoid the pin/password like I can with a simple `ssh foo`? 

Added a comment
diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_1_1b23963d04c5bd53d3de09970816fad8._comment b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_1_1b23963d04c5bd53d3de09970816fad8._comment
new file mode 100644
index 000000000..6adef9d9e
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__/comment_1_1b23963d04c5bd53d3de09970816fad8._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Atemu"
+ avatar="http://cdn.libravatar.org/avatar/d1f0f4275931c552403f4c6707bead7a"
+ subject="comment 1"
+ date="2021-05-04T12:46:59Z"
+ content="""
+I've got a fix done for this locally but it's unconditional for now. What's the best way of making this a configure flag or something similar so that users can disable it should they not want it? Not too familiar with Haskell standards on this sort of thing.
+"""]]

diff --git a/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__.mdwn b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__.mdwn
new file mode 100644
index 000000000..fd28ed7aa
--- /dev/null
+++ b/doc/todo/support_macOS__39___cp_-c___40__cp_--reflink_equivalent__41__.mdwn
@@ -0,0 +1,3 @@
+macOS has CoW copies too but they're only available via the `/bin/cp` binary as GNU coreutils doesn't support using macOS' calls for this unfortunately.
+
+One trouble here is that it doesn't automatically fall back to a non-reflink copy when a reflink copy is not possible, so that would have to be handled by us somehow.

smudge: check for known annexed inodes before checking annex.largefiles
smudge: Fix a case where an unlocked annexed file that annex.largefiles
does not match could get its unchanged content checked into git, due to git
running the smudge filter unecessarily.
When the file has the same inodecache as an already annexed file,
we can assume that the user is not intending to change how it's stored in
git.
Note that checkunchangedgitfile already handled the inverse case, where the
file was added to git previously. That goes further and actually sha1
hashes the new file and checks if it's the same hash in the index.
It would be possible to generate a key for the file and see if it's the
same as the old key, however that could be considerably more expensive than
sha1 of a small file is, and it is not necessary for the case I have, at
least, where the file is not modified or touched, and so its inode will
match the cache.
diff --git a/CHANGELOG b/CHANGELOG
index ed896c8c6..f2ca20673 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,9 @@ git-annex (8.20210429) UNRELEASED; urgency=medium
 
   * fromkey: Create an unlocked file when used in an adjusted branch
     where the file should be unlocked, or when configured by annex.addunlocked.
+  * smudge: Fix a case where an unlocked annexed file that annex.largefiles
+    does not match could get its unchanged content checked into git,
+    due to git running the smudge filter unecessarily.
 
  -- Joey Hess <id@joeyh.name>  Mon, 03 May 2021 10:33:10 -0400
 
diff --git a/Command/Smudge.hs b/Command/Smudge.hs
index 3e9b153cb..3c73022fc 100644
--- a/Command/Smudge.hs
+++ b/Command/Smudge.hs
@@ -168,25 +168,26 @@ clean file = do
 		filepath <- liftIO $ absPath file
 		return $ not $ dirContains repopath filepath
 
--- If annex.largefiles is configured, matching files are added to the
--- annex. But annex.gitaddtoannex can be set to false to disable that.
+-- If annex.largefiles is configured (and not disabled by annex.gitaddtoannex
+-- being set to false), matching files are added to the annex and the rest to
+-- git.
 --
 -- When annex.largefiles is not configured, files are normally not
--- added to the annex, so will be added to git. But some heuristics
--- are used to avoid bad behavior:
+-- added to the annex, so will be added to git. However, if the file
+-- is annexed in the index, keep it annexed. This prevents accidental
+-- conversions when previously annexed files get modified and added.
 --
--- If the file is annexed in the index, keep it annexed.
--- This prevents accidental conversions.
---
--- Otherwise, when the file's inode is the same as one that was used for
--- annexed content before, annex it. This handles cases such as renaming an
--- unlocked annexed file followed by git add, which the user naturally
--- expects to behave the same as git mv.
+-- In either case, if the file's inode is the same as one that was used
+-- for annexed content before, annex it. And if the file is not annexed
+-- in the index, and has the same content, leave it in git.
+-- This handles cases such as renaming a file followed by git add,
+-- which the user naturally expects to behave the same as git mv.
 shouldAnnex :: RawFilePath -> Maybe (Sha, FileSize, ObjectType) -> Maybe Key -> Annex Bool
-shouldAnnex file indexmeta moldkey = ifM (annexGitAddToAnnex <$> Annex.getGitConfig)
-	( checkunchangedgitfile $ checkmatcher checkheuristics
-	, checkunchangedgitfile checkheuristics
-	)
+shouldAnnex file indexmeta moldkey = do
+	ifM (annexGitAddToAnnex <$> Annex.getGitConfig)
+		( checkunchanged $ checkmatcher checkwasannexed
+		, checkunchanged checkwasannexed
+		)
   where
 	checkmatcher d
 		| dotfile file = ifM (getGitConfigVal annexDotFiles)
@@ -199,14 +200,21 @@ shouldAnnex file indexmeta moldkey = ifM (annexGitAddToAnnex <$> Annex.getGitCon
 			matcher <- largeFilesMatcher
 			checkFileMatcher' matcher file d
 	
-	checkheuristics = case moldkey of
-		Just _ -> return True
-		Nothing -> checkknowninode
+	checkwasannexed = pure $ isJust moldkey
 
-	checkknowninode = withTSDelta (liftIO . genInodeCache file) >>= \case
+	isknownannexedinode = withTSDelta (liftIO . genInodeCache file) >>= \case
 		Nothing -> pure False
 		Just ic -> Database.Keys.isInodeKnown ic =<< sentinalStatus
 
+	-- If the inode matches one known used for annexed content,
+	-- keep the file annexed. This handles a case where the file
+	-- has been annexed before, and the git is running the clean filter
+	-- again on it for whatever reason.
+	checkunchanged cont = ifM isknownannexedinode
+		( return True
+		, checkunchangedgitfile cont
+		)
+
 	-- This checks for a case where the file had been added to git
 	-- previously, not to the annex before, and its content is not
 	-- changed, but git is running the clean filter again on it
diff --git a/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_2_9bd32b89d0521fd1bec94683dffb4ecd._comment b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_2_9bd32b89d0521fd1bec94683dffb4ecd._comment
new file mode 100644
index 000000000..2415d2a51
--- /dev/null
+++ b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_2_9bd32b89d0521fd1bec94683dffb4ecd._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2021-05-03T16:26:26Z"
+ content="""
+I think this is a bug.
+
+The smudge/clean filter already handles several similar cases so ought to
+also be able to handle this one.
+
+I've made a change that seems to work, and will *probably* not break other
+cases, although this is a complex and subtle area.
+"""]]

close
diff --git a/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly.mdwn b/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly.mdwn
index 0914278b8..049e2c28b 100644
--- a/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly.mdwn
+++ b/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly.mdwn
@@ -179,3 +179,5 @@ git-annex: get: 1 failed
 ### Conclusion
 
 I'm so attracted to git-annex's idea, but so sad it's still not robust enough to use on Windows platform - v5 direct mode repo is as far as I can get, yet it still throws away my data like this...
+
+> [[done]]; this was apparently a bug with direct mode. --[[Joey]]
diff --git a/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly/comment_2_c500a0629048af1fe35c62dd27c8f1c3._comment b/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly/comment_2_c500a0629048af1fe35c62dd27c8f1c3._comment
new file mode 100644
index 000000000..c4817516f
--- /dev/null
+++ b/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly/comment_2_c500a0629048af1fe35c62dd27c8f1c3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2021-05-03T16:23:16Z"
+ content="""
+Thanks for checking up on this old bug.
+
+I think it makes sense that the bug was in the direct mode code, and so
+closing.
+"""]]

Added a comment
diff --git a/doc/bugs/Improvements_to_S3_glacier_integration/comment_4_f01d33d28c07cd87cb863b60b202dddd._comment b/doc/bugs/Improvements_to_S3_glacier_integration/comment_4_f01d33d28c07cd87cb863b60b202dddd._comment
new file mode 100644
index 000000000..f65153e7d
--- /dev/null
+++ b/doc/bugs/Improvements_to_S3_glacier_integration/comment_4_f01d33d28c07cd87cb863b60b202dddd._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="ijc@c69abafeb65fa2e784811fc549e9976a5cf4b903"
+ nickname="ijc"
+ avatar="http://cdn.libravatar.org/avatar/83432d9f01a0bedc575703583f7aa7c6"
+ subject="comment 4"
+ date="2021-05-03T15:45:14Z"
+ content="""
+Thanks Lukey. I'm not really sure how I missed (or how I found and then for some reason discounted) the glacier-cli backend but I think the fact I've started with s3 means I'm stuck with it unless I want to reupload a dozen TB of data and/or pay enormous retrieval/move fees (AIUI this is a property of the AWS end of things, not a git-annex issue, although s3 DEEP_ARCHIVE uses Glacier it's not the same objects/apis as going at glacier direct).
+
+FWIW the docs for storageclass at https://git-annex.branchable.com/special_remotes/S3/ refer one to s3cmd(1) for the list of valid values which includes DEEP_ARCHIVE, so that might be how I came to do things this way. Perhaps a pointer to glacier-cli at that point would be appropriate?
+
+I also just found https://git-annex.branchable.com/todo/wishlist__58___Restore_s3_files_moved_to_Glacier/ which is related to this but involves s3 lifecycles moving things between s3 and glacier on schedules etc which I think precludes glacier-cli. I've used that in other contexts (perhaps another reason I ended up following this path here too) but never with git-annex.
+"""]]

fromkey unlocked files support
fromkey: Create an unlocked file when used in an adjusted branch where the
file should be unlocked, or when configured by annex.addunlocked.
There is some overlap with code in Annex.Ingest, however it's not quite the
same because ingesting has a temp file with the content, where here the
content, if any, is in the annex object file. So it eg, makes sense for
Annex.Ingest to copy the execute mode of the content file, but it does not make
sense for fromkey to do that.
Also changed in passing to stage the file in git directly, rather than
using git add. One consequence of that is that if the file is gitignored,
it will still get added, rather than the old behavior:
The following paths are ignored by one of your .gitignore files:
ignored
hint: Use -f if you really want to add them.
hint: Turn this message off by running
hint: "git config advice.addIgnoredFile false"
git-annex: user error (xargs ["-0","git","--git-dir=.git","--work-tree=.","--literal-pathspecs","add","--"] exited 123)
That old behavior was a surprise to me, and so I consider it a bug, and doubt
anyone would have relied on it.
Note that, when on an --hide-missing branch, it is possible to fromkey a key
that is not present (needs --force). The annex link or pointer file still gets
written in this case. It doesn't seem to make any sense not to write it,
because then fromkey would not do anything useful in this case, and this way
the file can be committed and synced to master, and the branch re-adjusted to
hide the new missing file.
This commit was sponsored by Noam Kremen on Patreon.
diff --git a/Annex/Ingest.hs b/Annex/Ingest.hs
index 238eff5ea..e6450a18d 100644
--- a/Annex/Ingest.hs
+++ b/Annex/Ingest.hs
@@ -387,19 +387,10 @@ addAnnexedFile ci matcher file key mtmp = ifM (addUnlocked matcher mi (isJust mt
 			, matchFile = file
 			, matchKey = Just key
 			}
-		-- Provide as much info as we can without access to the
-		-- file's content.
-		Nothing -> MatchingInfo $ ProvidedInfo
-			{ providedFilePath = Just file
-			, providedKey = Just key
-			, providedFileSize = Nothing
-			, providedMimeType = Nothing
-			, providedMimeEncoding = Nothing
-			, providedLinkType = Nothing
-			}
+		Nothing -> keyMatchInfoWithoutContent key file
 	
 	linkunlocked mode = linkFromAnnex key file mode >>= \case
-		LinkAnnexFailed -> liftIO $ writepointer mode
+		LinkAnnexFailed -> writepointer mode
 		_ -> return ()
 	
 	writepointer mode = liftIO $ writePointerFile file key mode
diff --git a/CHANGELOG b/CHANGELOG
index 7695c6e2c..ed896c8c6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+git-annex (8.20210429) UNRELEASED; urgency=medium
+
+  * fromkey: Create an unlocked file when used in an adjusted branch
+    where the file should be unlocked, or when configured by annex.addunlocked.
+
+ -- Joey Hess <id@joeyh.name>  Mon, 03 May 2021 10:33:10 -0400
+
 git-annex (8.20210428) upstream; urgency=medium
 
   * New annex.private and remote.name.annex-private configs that can
diff --git a/Command/FromKey.hs b/Command/FromKey.hs
index 4055bd3ad..eadb89fd1 100644
--- a/Command/FromKey.hs
+++ b/Command/FromKey.hs
@@ -1,22 +1,23 @@
 {- git-annex command
  -
- - Copyright 2010-2019 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2021 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
 
-{-# LANGUAGE BangPatterns #-}
-
 module Command.FromKey where
 
 import Command
-import qualified Annex.Queue
+import qualified Annex
+import qualified Database.Keys
+import qualified Backend.URL
 import Annex.Content
 import Annex.WorkTree
 import Annex.Perms
-import qualified Annex
-import qualified Backend.URL
-import qualified Utility.RawFilePath as R
+import Annex.Link
+import Annex.FileMatcher
+import Annex.Ingest
+import Git.FilePath
 
 import Network.URI
 
@@ -37,16 +38,18 @@ optParser desc = FromKeyOptions
 	<*> parseBatchOption
 
 seek :: FromKeyOptions -> CommandSeek
-seek o = case (batchOption o, keyFilePairs o) of
-	(Batch fmt, _) -> seekBatch fmt
-	-- older way of enabling batch input, does not support BatchNull
-	(NoBatch, []) -> seekBatch BatchLine
-	(NoBatch, ps) -> do
-		force <- Annex.getState Annex.force
-		withPairs (commandAction . start force) ps
+seek o = do
+	matcher <- addUnlockedMatcher
+	case (batchOption o, keyFilePairs o) of
+		(Batch fmt, _) -> seekBatch matcher fmt
+		-- older way of enabling batch input, does not support BatchNull
+		(NoBatch, []) -> seekBatch matcher BatchLine
+		(NoBatch, ps) -> do
+			force <- Annex.getState Annex.force
+			withPairs (commandAction . start matcher force) ps
 
-seekBatch :: BatchFormat -> CommandSeek
-seekBatch fmt = batchInput fmt parse (commandAction . go)
+seekBatch :: AddUnlockedMatcher -> BatchFormat -> CommandSeek
+seekBatch matcher fmt = batchInput fmt parse (commandAction . go)
   where
 	parse s = do
 		let (keyname, file) = separate (== ' ') s
@@ -59,10 +62,10 @@ seekBatch fmt = batchInput fmt parse (commandAction . go)
 	go (si, (file, key)) = 
 		let ai = mkActionItem (key, file)
 		in starting "fromkey" ai si $
-			perform key file
+			perform matcher key file
 
-start :: Bool -> (SeekInput, (String, FilePath)) -> CommandStart
-start force (si, (keyname, file)) = do
+start :: AddUnlockedMatcher -> Bool -> (SeekInput, (String, FilePath)) -> CommandStart
+start matcher force (si, (keyname, file)) = do
 	let key = keyOpt keyname
 	unless force $ do
 		inbackend <- inAnnex key
@@ -70,7 +73,7 @@ start force (si, (keyname, file)) = do
 			"key ("++ keyname ++") is not present in backend (use --force to override this sanity check)"
 	let ai = mkActionItem (key, file')
 	starting "fromkey" ai si $
-		perform key file'
+		perform matcher key file'
   where
 	file' = toRawFilePath file
 
@@ -89,16 +92,32 @@ keyOpt s = case parseURI s of
 		Just k -> k
 		Nothing -> giveup $ "bad key/url " ++ s
 
-perform :: Key -> RawFilePath -> CommandPerform
-perform key file = lookupKeyNotHidden file >>= \case
+perform :: AddUnlockedMatcher -> Key -> RawFilePath -> CommandPerform
+perform matcher key file = lookupKeyNotHidden file >>= \case
 	Nothing -> ifM (liftIO $ doesFileExist (fromRawFilePath file))
 		( hasothercontent
 		, do
-			link <- calcRepo $ gitAnnexLink file key
-			createWorkTreeDirectory (parentDir file)
-			liftIO $ R.createSymbolicLink link file
-			Annex.Queue.addCommand [] "add" [Param "--"]
-				[fromRawFilePath file]
+			contentpresent <- inAnnex key
+			objectloc <- calcRepo (gitAnnexLocation key)
+			let mi = if contentpresent
+				then MatchingFile $ FileInfo
+					{ contentFile = objectloc
+					, matchFile = file
+					, matchKey = Just key
+					}
+				else keyMatchInfoWithoutContent key file
+			ifM (addUnlocked matcher mi contentpresent)
+				( do
+					stagePointerFile file Nothing =<< hashPointerFile key
+					Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath file)
+					if contentpresent
+						then linkunlocked
+						else writepointer
+				, do
+					link <- calcRepo $ gitAnnexLink file key
+					createWorkTreeDirectory (parentDir file)
+					addAnnexLink link file
+				)
 			next $ return True
 		)
 	Just k
@@ -108,3 +127,9 @@ perform key file = lookupKeyNotHidden file >>= \case
 	hasothercontent = do
 		warning $ fromRawFilePath file ++ " already exists with different content"
 		next $ return False
+	
+	linkunlocked = linkFromAnnex key file Nothing >>= \case
+		LinkAnnexFailed -> writepointer
+		_ -> return ()
+	
+	writepointer = liftIO $ writePointerFile file key Nothing
diff --git a/Types/FileMatcher.hs b/Types/FileMatcher.hs
index cf251cd47..005934b9e 100644
--- a/Types/FileMatcher.hs
+++ b/Types/FileMatcher.hs
@@ -47,6 +47,16 @@ data ProvidedInfo = ProvidedInfo
 	, providedLinkType :: Maybe LinkType
 	}
 
+keyMatchInfoWithoutContent :: Key -> RawFilePath -> MatchInfo
+keyMatchInfoWithoutContent key file = MatchingInfo $ ProvidedInfo
+	{ providedFilePath = Just file
+	, providedKey = Just key
+	, providedFileSize = Nothing
+	, providedMimeType = Nothing
+	, providedMimeEncoding = Nothing
+	, providedLinkType = Nothing
+	}
+
 -- This is used when testing a matcher, with values to match against
 -- provided by the user.
 data UserProvidedInfo = UserProvidedInfo
diff --git a/doc/bugs/git-annex-fromkey_broken_on_Windows.mdwn b/doc/bugs/git-annex-fromkey_broken_on_Windows.mdwn
index 4aa7ee5bd..68c1fdb60 100644

(Diff truncated)
diff --git a/doc/bugs/git-annex-fromkey_broken_on_Windows.mdwn b/doc/bugs/git-annex-fromkey_broken_on_Windows.mdwn
new file mode 100644
index 000000000..4aa7ee5bd
--- /dev/null
+++ b/doc/bugs/git-annex-fromkey_broken_on_Windows.mdwn
@@ -0,0 +1,27 @@
+Hi Joey,
+
+
+### Please describe the problem.
+`git annex fromkey` on Windows fails with `git-annex: System.PosixCompat.Files.createSymbolicLink: not supported: illegal operation`
+
+I guess it should create a unlocked file instead on Windows.
+
+### What steps will reproduce the problem?
+
+    mkdir test
+    cd test
+    git init
+    git annex init test
+    touch file
+    git annex add file
+    git annex sync
+    git annex fromkey SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 file2
+
+### What version of git-annex are you using? On what operating system?
+git version 2.31.1.windows.1 <br>
+git annex 8.20210331-g1fb59a63a <br>
+Windows 10 Pro 1903 <br>
+
+### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
+Yes! git-annex is really great and there is nothing else like it. 
+

Added a comment
diff --git a/doc/forum/PDF-related_error_when_running_git-annex-add_or_git-annex-status/comment_1_4df2625cc1f1de8f164aa9500eb80e13._comment b/doc/forum/PDF-related_error_when_running_git-annex-add_or_git-annex-status/comment_1_4df2625cc1f1de8f164aa9500eb80e13._comment
new file mode 100644
index 000000000..e85e204c6
--- /dev/null
+++ b/doc/forum/PDF-related_error_when_running_git-annex-add_or_git-annex-status/comment_1_4df2625cc1f1de8f164aa9500eb80e13._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-03T12:33:32Z"
+ content="""
+Git on Windows configures a diff driver by default, which is probably throwing these errors (For whathever reason... sigh). It's the `diff.astextplain.textconv` setting that you have to unset. I.e. Launch Git Bash as Administrator and run `git config --unset --system diff.astextplain.textconv`.
+"""]]

removed
diff --git a/doc/forum/PDF-related_error_when_running_git-annex-add_or_git-annex-status/comment_1_0fefd3bb7646eedfa6bfcd1b5a05e181._comment b/doc/forum/PDF-related_error_when_running_git-annex-add_or_git-annex-status/comment_1_0fefd3bb7646eedfa6bfcd1b5a05e181._comment
deleted file mode 100644
index 99e583797..000000000
--- a/doc/forum/PDF-related_error_when_running_git-annex-add_or_git-annex-status/comment_1_0fefd3bb7646eedfa6bfcd1b5a05e181._comment
+++ /dev/null
@@ -1,8 +0,0 @@
-[[!comment format=mdwn
- username="Lukey"
- avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
- subject="comment 1"
- date="2020-10-21T19:10:01Z"
- content="""
-Git on windows configures a diff driver by default, which is probably throwing these errors (For whathever reason... *sigh*). It's the `diff.<driver>.command` setting that you have to unset.
-"""]]

Added a comment
diff --git a/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly/comment_1_30cb5eebae1e90db75ed5e3fa237c1da._comment b/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly/comment_1_30cb5eebae1e90db75ed5e3fa237c1da._comment
new file mode 100644
index 000000000..04fb774b0
--- /dev/null
+++ b/doc/bugs/data_loss_on_Windows__58___git_annex_sync_--no-content_drops_last_copy_unexpectedly/comment_1_30cb5eebae1e90db75ed5e3fa237c1da._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-03T12:12:17Z"
+ content="""
+I tested it with the latest git-annex version (8.20210331-g1fb59a63a) and can't reproduce the bug. So I guess this can be closed.
+"""]]

Added a comment
diff --git a/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_1_9e4604f3c7ca9be1fe6a7020fee2fd96._comment b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_1_9e4604f3c7ca9be1fe6a7020fee2fd96._comment
new file mode 100644
index 000000000..e9b191689
--- /dev/null
+++ b/doc/forum/one-off_unlocked_annex_files_that_go_against_large/comment_1_9e4604f3c7ca9be1fe6a7020fee2fd96._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-03T11:04:30Z"
+ content="""
+AFAIK, this is a long known bug and fixing it is hard/impossible. I can't find the original bug report thought.
+"""]]

Added a comment
diff --git a/doc/bugs/sync_merges_local-to-repo_adjusted_branch/comment_1_9f017818750bc44b0793f2e8c85aed19._comment b/doc/bugs/sync_merges_local-to-repo_adjusted_branch/comment_1_9f017818750bc44b0793f2e8c85aed19._comment
new file mode 100644
index 000000000..7180d081e
--- /dev/null
+++ b/doc/bugs/sync_merges_local-to-repo_adjusted_branch/comment_1_9f017818750bc44b0793f2e8c85aed19._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-03T10:26:35Z"
+ content="""
+Hmm, from the output above, it is just updating the remote-tracking branch. So it shouldn't affect the local `adjusted/master(hidemissing)` branch at all.
+"""]]

update
diff --git a/doc/todo/move_readonly_values_to_AnnexRead.mdwn b/doc/todo/move_readonly_values_to_AnnexRead.mdwn
index 691e660cd..b14627df7 100644
--- a/doc/todo/move_readonly_values_to_AnnexRead.mdwn
+++ b/doc/todo/move_readonly_values_to_AnnexRead.mdwn
@@ -3,3 +3,10 @@ and reading values from it is faster (no MVar). So,
 anything that never needs to be modified while git-annex is running can be
 moved to AnnexRead for a performance win and also to make clean how it's
 used. --[[Joey]]
+
+The easy things have been moved now, but some things like Annex.force and
+Annex.fast would be good to move. Moving those would involve running
+argument processing outside the Annex monad. The main reason argument
+processing runs in the Annex monad is to set those values, but there may be
+other reasons too, so this will be a large set of changes that need to all
+happen together. --[[Joey]]

Added a comment
diff --git a/doc/bugs/Improvements_to_S3_glacier_integration/comment_3_69e249605f2252f3fb6f45354e1fd5cc._comment b/doc/bugs/Improvements_to_S3_glacier_integration/comment_3_69e249605f2252f3fb6f45354e1fd5cc._comment
new file mode 100644
index 000000000..103c5da18
--- /dev/null
+++ b/doc/bugs/Improvements_to_S3_glacier_integration/comment_3_69e249605f2252f3fb6f45354e1fd5cc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 3"
+ date="2021-05-02T18:46:34Z"
+ content="""
+Sorry, I just noticed that you are using s3 and not glacier-cli (which the [[special_remotes/glacier/]] special-remote uses). So it indeed is a bug, since git-annex doesn't handle glacier with s3 as yet far as I know. Maybe you have more luck with the glacier special-remote?
+"""]]

Added a comment
diff --git a/doc/forum/Make_GA_aware_of_externally-made_copies/comment_1_0e2edea494810a8614f628ec46b934e4._comment b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_1_0e2edea494810a8614f628ec46b934e4._comment
new file mode 100644
index 000000000..778e02856
--- /dev/null
+++ b/doc/forum/Make_GA_aware_of_externally-made_copies/comment_1_0e2edea494810a8614f628ec46b934e4._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-02T18:36:56Z"
+ content="""
+Hi,
+I tested it with `encryption=shared` and it works, but not with chunking. When creating the 2nd remote, you have to look up the cipher of the first one with `git cat-file blob git-annex:remote.log` and pass it to initremote with `cipher=`. Finally, after externally copying everything from the 1st remote to the 2nd remote, you have to run `git annex fsck --fast --all --from=remote2` to make git-annex aware of the copies.
+"""]]

diff --git a/doc/forum/Make_GA_aware_of_externally-made_copies.mdwn b/doc/forum/Make_GA_aware_of_externally-made_copies.mdwn
new file mode 100644
index 000000000..761a1ba7c
--- /dev/null
+++ b/doc/forum/Make_GA_aware_of_externally-made_copies.mdwn
@@ -0,0 +1,15 @@
+I use a backup service which mirrors the contents of directories to The Cloud^(TM). One of the dirs I make it mirror is a directory special remote with encryption and chunking which I move data into.  
+Now I would like to make GA aware of the second copy that the mirroring service creates of that special remote.
+
+I use BTRFS as the underlying FS, so my idea is it to store the special remote inside a subvolume and then snapshot it before sending it off to mirror. (The same could probably be done with hardlinks as special remotes are read- and unlink-only.) This way I've got a local directory which represents the state of the remote mirror once the service's tool is done uploading it.
+
+My idea was to then let GA know about it in the form of a second directory special remote to give me the correct numcopies count.
+
+The problem I have run into here is that there does not seem to be a way to get GA to "import" pre-existing state of a directory special remote. I just can't get it to recognise the existance of the keys inside it.
+
+I could probably hack up an something that could query the mirrored keys directly and maybe make a special remote out of that but the same problem would apply here as it's still a special remote that changes outside of GA's control.
+
+Is there a way of doing what I want that I may have overlooked? Is there a better way of making GA aware of this external copy perhaps?
+
+Thanks,
+- Atemu

Added a comment
diff --git a/doc/bugs/Improvements_to_S3_glacier_integration/comment_2_53fdb046440d7801e784c56c6ff9e1df._comment b/doc/bugs/Improvements_to_S3_glacier_integration/comment_2_53fdb046440d7801e784c56c6ff9e1df._comment
new file mode 100644
index 000000000..b0c2fc5fc
--- /dev/null
+++ b/doc/bugs/Improvements_to_S3_glacier_integration/comment_2_53fdb046440d7801e784c56c6ff9e1df._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="ijc@c69abafeb65fa2e784811fc549e9976a5cf4b903"
+ nickname="ijc"
+ avatar="http://cdn.libravatar.org/avatar/83432d9f01a0bedc575703583f7aa7c6"
+ subject="comment 2"
+ date="2021-05-02T17:54:56Z"
+ content="""
+I don't think git-annex is starting any retrieval process, I have to do it manually. I wasn't sure if it was supposed to (it doesn't seem to try) but maybe that's an aspect of this bug too.
+"""]]

Added a comment
diff --git a/doc/forum/dev_machine_-__62___NAS_-__62___cloud/comment_1_f77818a766f2b41d13ced2bcf4447de0._comment b/doc/forum/dev_machine_-__62___NAS_-__62___cloud/comment_1_f77818a766f2b41d13ced2bcf4447de0._comment
new file mode 100644
index 000000000..b33329dbd
--- /dev/null
+++ b/doc/forum/dev_machine_-__62___NAS_-__62___cloud/comment_1_f77818a766f2b41d13ced2bcf4447de0._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="Lukey"
+ avatar="http://cdn.libravatar.org/avatar/c7c08e2efd29c692cc017c4a4ca3406b"
+ subject="comment 1"
+ date="2021-05-02T08:03:56Z"
+ content="""
+I guess you could just put something like this in your crontab:
+`*/5 * * * * cd /path/to/repo; flock -n .git/periodic-sync.lock git annex sync --content --all`
+
+As a optimization, you could only sync with `--content --all` if the git-annex branch changed since the last time it ran.
+"""]]

diff --git a/doc/forum/dev_machine_-__62___NAS_-__62___cloud.mdwn b/doc/forum/dev_machine_-__62___NAS_-__62___cloud.mdwn
index 3ae2192a1..5fbec8173 100644
--- a/doc/forum/dev_machine_-__62___NAS_-__62___cloud.mdwn
+++ b/doc/forum/dev_machine_-__62___NAS_-__62___cloud.mdwn
@@ -3,3 +3,5 @@ I have a setup right now with a dev machine, a local NAS drive, and offsite clou
 Apparently I can't run assistant in a bare repository, which is what's on NAS. And, I'm not even sure assistant is the right thing, I think maybe it does more than just sync content.
 
 What's a good way to set this up so that when NAS receives `annex sync` content, it immediately does its own `annex sync` to cloud remote?
+
+One thing I can think of is set up a `update` / `post-receive` hook to touch a file on the NAS. Then have a cron job check for the file, and if it's there, start a cloud sync.

diff --git a/doc/forum/dev_machine_-__62___NAS_-__62___cloud.mdwn b/doc/forum/dev_machine_-__62___NAS_-__62___cloud.mdwn
new file mode 100644
index 000000000..3ae2192a1
--- /dev/null
+++ b/doc/forum/dev_machine_-__62___NAS_-__62___cloud.mdwn
@@ -0,0 +1,5 @@
+I have a setup right now with a dev machine, a local NAS drive, and offsite cloud storage. I want annex content to flow that way: so I `git annex sync nas` from my dev box, then I SSH into the NAS and `git annex sync cloud`. It's this last part that I want to automate - I want to make sure that any content I sync to NAS, gets synced from NAS to cloud. I don't want my dev machine uploading directly to cloud unless I explicitly set that.
+
+Apparently I can't run assistant in a bare repository, which is what's on NAS. And, I'm not even sure assistant is the right thing, I think maybe it does more than just sync content.
+
+What's a good way to set this up so that when NAS receives `annex sync` content, it immediately does its own `annex sync` to cloud remote?

initial todo asking for possibility to assign costs per URL
diff --git a/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__.mdwn b/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__.mdwn
new file mode 100644
index 000000000..12d6ca372
--- /dev/null
+++ b/doc/todo/assign_costs_per_URL_or_better_repo-wide___40__regexes__41__.mdwn
@@ -0,0 +1,58 @@
+I could have bet all my savings (well, not that much anyways - kids keep eating) that there was a way to give different costs for different URLs.  I believe it was in the same spirit as `remote.<name>.annex-cost-command` - that there could be a command which then be used to prioritize one url over another.  But I fail to find any hint on it
+
+<details>
+<summary>e.g. nothing in `cost` related config vars</summary> 
+
+```shell
+$> grep '^\*.*cost' doc/git-annex.mdwn
+* `remote.<name>.annex-cost`
+* `remote.<name>.annex-cost-command`
+
+$> grep '^\*.*web' doc/git-annex.mdwn 
+* `webapp`
+* `remote.<name>.annex-webdav`
+* `annex.web-options`
+
+$> grep '^\*.*url' doc/git-annex.mdwn
+* `addurl [url ...]`
+* `rmurl file url`
+* `importfeed [url ...]`
+* `registerurl [key url]`
+* `unregisterurl [key url]`
+* `remote.<name>.annex-rsyncurl`
+* `annex.security.allowed-url-schemes`
+
+```
+</details>
+
+but even with such command it would have made it not really fit my need -- I would like to assign costs and propagate that information through the clones without requiring users to install additional commands or configure their clones.
+
+Use case: 
+
+For the same file we provide API end-point which redirects to a minted url (with content-disposition etc), and file could be accessed directly from that url.  E.g. both 
+https://api.dandiarchive.org/api/dandisets/000027/versions/draft/assets/ff453f4c-a435-4a5d-a48b-128abca5ec47/download/
+and
+https://dandiarchive.s3.amazonaws.com/blobs/2db/af0/2dbaf0fd-5003-4a0a-b4c0-bc8cdbdb3826
+point to the same (small) file.
+
+I would like git-annex to know both, since if we migrate backend storage, I would like users to still be able to access via api url.  But by default, while still works, I would like them to access via direct url to s3.
+
+ATM, regardless of the order in which I add those two urls to a file, git-annex seems (didn't look in the code etc) to use them in a "sorted" order, so it would go for the API one, thus causing unnecessary url minting etc.  I would like to make direct url having lower cost so it would be preferred over the api one.
+
+May be there is a way already?  
+
+If not, I think it could be flexibly achieved if in `git annex config` I could provide url regexes with costs.  Then I could encode that information while allowing users/clones to tune it if becomes desired.  If possible, smth like
+
+```
+# assuming default cost of web remote 100 if it is
+cost url-https?://api.dandiarchive.org/.* = 200
+```
+
+or alike in my case. May be it could even be like `[+-]COST` so it would then add or subtract from the cost of the remote, thus allowing to account for the remote cost if assigned/set and costs are considered across remotes and their URLs.
+
+Alternative could be - a cost per url (while registerurl or addurl) but IMHO that might be too much, and harder to tune per specific clone "globally".
+
+PS question -- how to see the costs?  `annex whereis --json FILE` seems to not provide them.
+
+[[!meta author=yoh]]
+[[!tag projects/dandi]]

initial todo for perspective copy-key(file) command(s)
diff --git a/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info.mdwn b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info.mdwn
new file mode 100644
index 000000000..58850799a
--- /dev/null
+++ b/doc/todo/copy-key___40__--batch__41___to_copy__47__merge_availability_info.mdwn
@@ -0,0 +1,14 @@
+An ability to copy key availability information from one git-annex'ed repo to another had been a use case we needed for quite some time. Michael even implemented [datalad copy-file](http://docs.datalad.org/en/stable/generated/datalad.api.copy_file.html?highlight=copy_file) remotes - that was an immediate use-case whenever it was necessary to craft "custom" smaller datasets from a much larger (super)dataset . And now we came to the same need to facilitate "splitting" a larger dataset into sub-datasets: [issues/600](https://github.com/datalad/datalad/issues/600#issuecomment-824715427).
+
+I think, in particular with [https://git-annex.branchable.com/todo/hiding_a_repository/](https://git-annex.branchable.com/todo/hiding_a_repository/), something like `git annex copy-key --from hidden-repo KEY` could become the ultimate tool for such operations.  Alternatively may be it could be `git annex copy-key --from-repo /repo/path KEY` so there would not even be a need to link original one as some hidden repo, but rather even "include" original one as a `git submodule` (e.g. `original/`).
+
+Such command would need to pretty much do whatever `git annex merge` already does, just limiting its effects to only relevant key(s) and only the remotes which are known to have that key.
+
+Although I concentrated on "copy-**key**" pretty much the same feature could be useful to provide a `git annex copy-file PATH1 PATH2 ... DEST` where PATH?s would be paths in other git-annex repo(s) -- so it would pretty be similar (just better since not only URLs copied) to `datalad copy-file`.
+
+`--batch` mode in both cases would be super handy to streamline use of the command(s).
+
+WDYT Joey?
+
+[[!meta author=yoh]]
+[[!tag projects/datalad]]

added suggestion: support tree-ish in command args
diff --git a/doc/todo/support_tree-ish_in_command_args.mdwn b/doc/todo/support_tree-ish_in_command_args.mdwn
new file mode 100644
index 000000000..83d033e13
--- /dev/null
+++ b/doc/todo/support_tree-ish_in_command_args.mdwn
@@ -0,0 +1 @@
+For commands like [[`git-annex-whereis`|git-annex-whereis]] that take a `path` argument, it would help if this could be generalized to taking a [tree-ish](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddeftree-ishatree-ishalsotreeish).  E.g. for `git-annex-whereis` this could be used to look up where previous file versions are stored.

Added a comment: openSUSE Leap 15.2
diff --git a/doc/install/openSUSE/comment_2_095d48e7dffe57421b2d3384a83d7183._comment b/doc/install/openSUSE/comment_2_095d48e7dffe57421b2d3384a83d7183._comment
new file mode 100644
index 000000000..6e0bc217e
--- /dev/null
+++ b/doc/install/openSUSE/comment_2_095d48e7dffe57421b2d3384a83d7183._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="daniel"
+ avatar="http://cdn.libravatar.org/avatar/2494072cb19027868a5111e94ad71986"
+ subject="openSUSE Leap 15.2"
+ date="2021-04-29T14:47:00Z"
+ content="""
+Confirm getting the following error on runnning zypper in git-annex:
+
+    Loading repository data...
+    Reading installed packages...
+    Package 'git-annex' not found.
+
+Looking at [software.opensuse](https://software.opensuse.org/package/git-annex) I found at least an experimental package, which seems to work for me:
+
+    zypper addrepo https://download.opensuse.org/repositories/devel:languages:haskell/openSUSE_Leap_15.2/devel:languages:haskell.repo
+    zypper refresh
+    zypper install git-annex
+
+"""]]

doc/git-annex-config: Fix typo in annex.synconlyannex description
diff --git a/doc/git-annex-config.mdwn b/doc/git-annex-config.mdwn
index ecea8c75d..daf5821c0 100644
--- a/doc/git-annex-config.mdwn
+++ b/doc/git-annex-config.mdwn
@@ -80,7 +80,7 @@ looks for these.
 
 * `annex.synconlyannex`
 
-  Set to true to make git-annex sync default to only sincing the git-annex
+  Set to true to make git-annex sync default to only sync the git-annex
   branch and annexed content.
 
 * `annex.securehashesonly`

add news item for git-annex 8.20210428
diff --git a/doc/news/version_8.20201129.mdwn b/doc/news/version_8.20201129.mdwn
deleted file mode 100644
index 4d6c0eee1..000000000
--- a/doc/news/version_8.20201129.mdwn
+++ /dev/null
@@ -1,38 +0,0 @@
-git-annex 8.20201129 released with [[!toggle text="these changes"]]
-[[!toggleable text="""  * New borg special remote. This is a new kind of remote, that examines
-    borg backups of git-annex repositories, learns what files have been
-    backed up, and can restore files from the backup and so on. As well
-    as backups, it can be useful for archival storage, since borg can
-    efficiently store many related versions of files.
-  * New config annex.stalldetection, remote.name.annex-stalldetection,
-    which can be used to deal with remotes that stall during transfers,
-    or are sometimes too slow to want to use.
-  * Support special remotes that are configured with importtree=yes but
-    without exporttree=yes.
-  * Fix bug that made the next download after an empty file from a ssh
-    or tor remote fail.
-  * Avoid spurious "verification of content failed" message when downloading
-    content from a ssh or tor remote fails due to the remote no longer
-    having a copy of the content.
-  * Fix bug that matched include= and exclude= in preferred/required content
-    expressions relative to the current directory, rather than the path
-    from the top of the repository.
-    (Reversion introduced in version 8.20201116.)
-  * Fix hang on shutdown of external special remote using ASYNC protocol
-    extension.
-    (Reversion introduced in version 8.20201007.)
-  * Guard against running in a repo where annex.uuid is set but
-    annex.version is not set, or vice-versa.
-  * Avoid autoinit when a repo does not have annex.version or annex.uuid
-    set, but has a git-annex objects directory, suggesting it was used
-    by git-annex before, and the git config may have been lost.
-  * importfeed: Avoid using youtube-dl when a feed does not contain an
-    enclosure, but only a link to an url which youtube-dl does not support.
-  * initremote: Prevent enabling encryption with exporttree=yes or
-    importtree=yes.
-  * Windows: include= and exclude= containing '/' will also match filenames
-    that are written using '\'. (And vice-versa, but it's better to use '/'
-    for portability.)
-  * Fix a bug that could prevent getting files from an importtree=yes
-    remote, because the imported tree was allowed to be garbage collected.
-  * stack.yaml: Updated to lts-16.27."""]]
\ No newline at end of file
diff --git a/doc/news/version_8.20210428.mdwn b/doc/news/version_8.20210428.mdwn
new file mode 100644
index 000000000..0e86ea40d
--- /dev/null
+++ b/doc/news/version_8.20210428.mdwn
@@ -0,0 +1,29 @@
+git-annex 8.20210428 released with [[!toggle text="these changes"]]
+[[!toggleable text="""  * New annex.private and remote.name.annex-private configs that can
+    prevent storing information about a repository and remotes in the
+    git-annex branch.
+  * initremote: Added --private option to set up a private special remote.
+  * importfeed: Made "checking known urls" phase run 12 times faster.
+  * Added --debugfilter (and annex.debugfilter)
+  * diffdriver: Support unlocked files.
+  * forget: Preserve currently exported trees, avoiding problems with
+    exporttree remotes in some unusual circumstances.
+  * fsck: When downloading content from a remote, if the content is able
+    to be verified during the transfer, skip checksumming it a second time.
+  * directory: When cp supports reflinks, use it.
+  * Avoid excess commits to the git-annex branch when stall detection is
+    enabled.
+  * git-annex-config: Allow setting annex.securehashesonly, which has
+    otherwise been supported since 2019, but was missing from the list of
+    allowed repo-global configs.
+  * init: Fix a crash when the repo's was cloned from a repo that had an
+    adjusted branch checked out, and the origin remote is not named "origin".
+  * Fix some bugs that made git-annex not see recently recorded status
+    information when configured with annex.alwayscommit=false.
+  * When mincopies is set to a larger value than numcopies, make sure that
+    mincopies is satisfied. Before, it assumed a sane configuration would
+    have numcopies larger or equal to mincopies. It's still a good idea
+    not to configure git-annex this way.
+  * Avoid more than 1 gpg password prompt at the same time, which
+    could happen occasionally before when concurrency is enabled.
+  * Fix build with persistent-2.12.0.1"""]]
\ No newline at end of file

Added a comment: I think I am having the same issue
diff --git a/doc/bugs/Failing_to_execute_bash_remotes_windows/comment_5_6a60930f3ecbe077eb60e6ca041d8933._comment b/doc/bugs/Failing_to_execute_bash_remotes_windows/comment_5_6a60930f3ecbe077eb60e6ca041d8933._comment
new file mode 100644
index 000000000..ae087c6ad
--- /dev/null
+++ b/doc/bugs/Failing_to_execute_bash_remotes_windows/comment_5_6a60930f3ecbe077eb60e6ca041d8933._comment
@@ -0,0 +1,53 @@
+[[!comment format=mdwn
+ username="datamanager"
+ avatar="http://cdn.libravatar.org/avatar/7d4ca7c5e571d4740ef072b83a746c12"
+ subject="I think I am having the same issue"
+ date="2021-04-28T01:19:46Z"
+ content="""
+Hello, I think I am having the same issue, though some particulars seem different. It's marked as solved, but what exactly is the solution? 
+
+I tried running `git annex enableremote --debug google-drive`, and got this output: 
+
+```
+[2021-04-28 01:11:19.033938395] read: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"show-ref\",\"git-annex\"]
+[2021-04-28 01:11:19.880161468] process done ExitSuccess
+[2021-04-28 01:11:19.881748395] read: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+[2021-04-28 01:11:20.742986051] process done ExitSuccess
+[2021-04-28 01:11:20.760170947] read: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"log\",\"refs/heads/git-annex..b8c2aac9d4d666ae5c8ee2041c643052ecf7dcbe\",\"--pretty=%H\",\"-n1\"]
+[2021-04-28 01:11:21.239519332] process done ExitSuccess
+[2021-04-28 01:11:21.240506519] read: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"log\",\"refs/heads/git-annex..bd130925066b8c62855ac88d4640bda4b4d14afa\",\"--pretty=%H\",\"-n1\"]
+[2021-04-28 01:11:21.621569176] process done ExitSuccess
+[2021-04-28 01:11:21.627188551] chat: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"cat-file\",\"--batch\"]
+[2021-04-28 01:11:21.629520009] chat: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"cat-file\",\"--batch-check=%(objectname) %(objecttype) %(objectsize)\"]
+enableremote google-drive [2021-04-28 01:11:22.153897457] chat: /data/data/com.termux/files/usr/bin/git-annex-remote-rclone []
+(encryption update) (to gpg keys: redacted) [2021-04-28 01:11:22.164967925] chat: /data/data/com.termux/files/usr/bin/git-annex-remote-rclone []
+
+git-annex: Cannot run /data/data/com.termux/files/usr/bin/git-annex-remote-rclone -- Make sure it's executable and that its dependencies are installed.
+failed
+[2021-04-28 01:11:22.1806623] process done ExitSuccess
+[2021-04-28 01:11:22.184542509] process done ExitSuccess
+git-annex: enableremote: 1 failed
+```
+
+This remote is configured with gpg, so I tried a test repository without encryption. I attempted to initialize it with `git annex initremote --debug google-drive type=external externaltype=rclone target=google-drive prefix=git-annex-android-test chunk=50MiB encryption=shared mac=HMACSHA512 rclone_layout=lower`, and got this output:
+
+```
+[2021-04-28 01:17:33.983261638] read: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"show-ref\",\"git-annex\"]
+[2021-04-28 01:17:34.314992575] process done ExitSuccess
+[2021-04-28 01:17:34.315285908] read: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+[2021-04-28 01:17:34.774339919] process done ExitSuccess
+[2021-04-28 01:17:34.810030752] read: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"log\",\"refs/heads/git-annex..ae1ad94cc2cf05b139560772923f5196793a1015\",\"--pretty=%H\",\"-n1\"]
+[2021-04-28 01:17:35.111290491] process done ExitSuccess
+[2021-04-28 01:17:35.125354033] chat: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"cat-file\",\"--batch\"]
+[2021-04-28 01:17:35.129850856] chat: git [\"--git-dir=.git\",\"--work-tree=.\",\"--literal-pathspecs\",\"cat-file\",\"--batch-check=%(objectname) %(objecttype) %(objectsize)\"]
+initremote google-drive [2021-04-28 01:17:35.690712627] chat: /data/data/com.termux/files/usr/bin/git-annex-remote-rclone []
+
+git-annex: Cannot run /data/data/com.termux/files/usr/bin/git-annex-remote-rclone -- Make sure it's executable and that its dependencies are installed.
+failed
+[2021-04-28 01:17:35.70162346] process done ExitSuccess
+[2021-04-28 01:17:35.703906741] process done ExitSuccess
+git-annex: initremote: 1 failed
+```
+
+Hopefully someone can help me, thanks!
+"""]]

close
test case ran for over an hour successfully
diff --git a/doc/bugs/fsck_of_encrypted_remote_fails_w__47___multiple_jobs.mdwn b/doc/bugs/fsck_of_encrypted_remote_fails_w__47___multiple_jobs.mdwn
index 0d48b6a60..4517f6a31 100644
--- a/doc/bugs/fsck_of_encrypted_remote_fails_w__47___multiple_jobs.mdwn
+++ b/doc/bugs/fsck_of_encrypted_remote_fails_w__47___multiple_jobs.mdwn
@@ -80,3 +80,5 @@ fsck whatisthis (checking s3...) ok
 
 
 `git-annex` is over all working very well for me. I am able to do some things that I've wanted to be able to do for years. I believe I have worked it out well enough that I can stop testing it and start using it for real.
+
+> [[fixed|done]] --[[Joey]]

Avoid more than 1 gpg password prompt at the same time
Which could happen occasionally before when concurrency is enabled.
While not much of a problem when it did happen, better to avoid it. Also,
since it seems likely the gpg-agent sometimes fails in such a situation,
this makes it not happen when running a single git-annex command with
concurrency enabled.
This commit was sponsored by Jake Vosloo on Patreon.
diff --git a/Annex.hs b/Annex.hs
index 7ccc0a1f5..5168b6411 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -122,6 +122,7 @@ data AnnexRead = AnnexRead
 	, transferrerpool :: TransferrerPool
 	, debugenabled :: Bool
 	, debugselector :: DebugSelector
+	, ciphers :: TMVar (M.Map StorableCipher Cipher)
 	}
 
 newAnnexRead :: GitConfig -> IO AnnexRead
@@ -132,6 +133,7 @@ newAnnexRead c = do
 	sc <- newTMVarIO False
 	si <- newTVarIO M.empty
 	tp <- newTransferrerPool
+	cm <- newTMVarIO M.empty
 	return $ AnnexRead
 		{ activekeys = emptyactivekeys
 		, activeremotes = emptyactiveremotes
@@ -141,6 +143,7 @@ newAnnexRead c = do
 		, transferrerpool = tp
 		, debugenabled = annexDebug c
 		, debugselector = debugSelectorFromGitConfig c
+		, ciphers = cm
 		}
 
 -- Values that can change while running an Annex action.
@@ -178,7 +181,6 @@ data AnnexState = AnnexState
 	, forcetrust :: TrustMap
 	, trustmap :: Maybe TrustMap
 	, groupmap :: Maybe GroupMap
-	, ciphers :: M.Map StorableCipher Cipher
 	, lockcache :: LockCache
 	, flags :: M.Map String Bool
 	, fields :: M.Map String String
@@ -237,7 +239,6 @@ newAnnexState c r = do
 		, forcetrust = M.empty
 		, trustmap = Nothing
 		, groupmap = Nothing
-		, ciphers = M.empty
 		, lockcache = M.empty
 		, flags = M.empty
 		, fields = M.empty
diff --git a/CHANGELOG b/CHANGELOG
index c4af69829..6179d8c3d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -25,6 +25,8 @@ git-annex (8.20210331) UNRELEASED; urgency=medium
     mincopies is satisfied. Before, it assumed a sane configuration would
     have numcopies larger or equal to mincopies. It's still a good idea
     not to configure git-annex this way.
+  * Avoid more than 1 gpg password prompt at the same time, which
+    could happen occasionally before when concurrency is enabled.
   * Fix build with persistent-2.12.0.1
 
  -- Joey Hess <id@joeyh.name>  Thu, 01 Apr 2021 12:17:26 -0400
diff --git a/Remote/Helper/Encryptable.hs b/Remote/Helper/Encryptable.hs
index 296f3836c..2e880b09f 100644
--- a/Remote/Helper/Encryptable.hs
+++ b/Remote/Helper/Encryptable.hs
@@ -1,6 +1,6 @@
 {- common functions for encryptable remotes
  -
- - Copyright 2011-2020 Joey Hess <id@joeyh.name>
+ - Copyright 2011-2021 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -30,6 +30,7 @@ import qualified Data.Map as M
 import qualified Data.Set as S
 import qualified "sandi" Codec.Binary.Base64 as B64
 import qualified Data.ByteString as B
+import Control.Concurrent.STM
 
 import Annex.Common
 import Types.Remote
@@ -218,18 +219,29 @@ remoteCipher c gc = fmap fst <$> remoteCipher' c gc
 {- Gets encryption Cipher. The decrypted Ciphers are cached in the Annex
  - state. -}
 remoteCipher' :: ParsedRemoteConfig -> RemoteGitConfig -> Annex (Maybe (Cipher, StorableCipher))
-remoteCipher' c gc = go $ extractCipher c
-  where
-	go Nothing = return Nothing
-	go (Just encipher) = do
-		cache <- Annex.getState Annex.ciphers
-		case M.lookup encipher cache of
+remoteCipher' c gc = case extractCipher c of
+	Nothing -> return Nothing
+	Just encipher -> do
+		cachev <- Annex.getRead Annex.ciphers
+		cachedciper <- liftIO $ atomically $ 
+			M.lookup encipher <$> readTMVar cachev
+		case cachedciper of
 			Just cipher -> return $ Just (cipher, encipher)
-			Nothing -> do
-				cmd <- gpgCmd <$> Annex.getGitConfig
-				cipher <- liftIO $ decryptCipher cmd (c, gc) encipher
-				Annex.changeState (\s -> s { Annex.ciphers = M.insert encipher cipher cache })
-				return $ Just (cipher, encipher)
+			-- Not cached; decrypt it, making sure
+			-- to only decrypt one at a time. Avoids
+			-- prompting for decrypting the same thing twice
+			-- when this is run concurrently.
+			Nothing -> bracketOnError
+				(liftIO $ atomically $ takeTMVar cachev)
+				(liftIO . atomically . putTMVar cachev)
+				(go cachev encipher)
+  where
+	go cachev encipher cache = do
+		cmd <- gpgCmd <$> Annex.getGitConfig
+		cipher <- liftIO $ decryptCipher cmd (c, gc) encipher
+		liftIO $ atomically $ putTMVar cachev $
+			M.insert encipher cipher cache
+		return $ Just (cipher, encipher)
 
 {- Checks if the remote's config allows storing creds in the remote's config.
  - 
diff --git a/doc/bugs/fsck_of_encrypted_remote_fails_w__47___multiple_jobs/comment_3_f053194ba612d1aa1ecddb8c9bf843ae._comment b/doc/bugs/fsck_of_encrypted_remote_fails_w__47___multiple_jobs/comment_3_f053194ba612d1aa1ecddb8c9bf843ae._comment
new file mode 100644
index 000000000..ad60bef9d
--- /dev/null
+++ b/doc/bugs/fsck_of_encrypted_remote_fails_w__47___multiple_jobs/comment_3_f053194ba612d1aa1ecddb8c9bf843ae._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2021-04-27T20:33:41Z"
+ content="""
+I've implemented the race protection. Pretty sure this fixes it, at least
+to the extent it can be fixed if it's a gpg bug that any 2 concurrent
+password prompts can sometimes trigger. I'll run git-annex fsck in a
+loop for an hour or so to be more sure.
+
+It would be nice if someone wants to file a bug on gpg, but I don't have
+time right now.
+"""]]