A bit late to the party, but I just tried #12653 and noticed some non-intuitive behavior (on macOS), that's probably worth explaining release notes and help.

Before this new feature I kept the entire datadir on an SSD drive, so I launch with: `bitcoind -datadir=/Volumes/SSD/Bitcoin`.

Initially I naively moved `/Volumes/SSD/Bitcoin/blocks` to `/Users/bitcoin/blocks` and added a line to `/Volumes/SSD/Bitcoin/bitcoin.conf`: `blocksdir=/Users/bitcoin/blocks`.

I then realized that I shouldn't have moved the `index` subdirectory, so I moved that back to `/Volumes/SSD/Bitcoin/blocks/index`. Having an empty `blocks` dir with just and `index` subdir is a bit weird. Perhaps after @jimpo's #11857 is merged, we could just move / assume all indexes to be there (if `-blocksdir` is set)?

Worse, it created a directory `/Users/bitcoin/blocks/blocks`, which seems like a bug. I had to set `blocksdir=/Users/bitcoin` instead.
pcoinsTip.reset(new CCoinsViewCache(pcoinscatcher.get()));
                bool is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull();
                if (!is_coinsview_empty) {
                    
                    if (!LoadChainTip(chainparams)) {
                        strLoadError = _("Error initializing block database");
                        break;
                    }
                    assert(chainActive.Tip() != nullptr);
                }
                if (!fReset) {
                    
                    
                    
                    uiInterface.InitMessage(_("Rewinding blocks..."));
                    if (!RewindBlockIndex(chainparams)) {
                        strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
                        break;
                    }
                }
                if (!is_coinsview_empty) {
                    uiInterface.InitMessage(_("Verifying blocks..."));
                    if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
                        LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
                            MIN_BLOCKS_TO_KEEP);
                    }
                    CBlockIndex* tip = chainActive.Tip();
                    RPCNotifyBlockChange(true, tip);
                    if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
                        strLoadError = _("The block database contains a block which appears to be from the future. "