Move friendly merge sort - follow-up
It certainly looks clean and well-written.
Just one thing, I really hate horizontal scrolling. I acknowlege this site is very restrictive there though.


Make sure your use of move-semantics is type-appropriate:


Move if it's a move-only type.
Move if moveing is noexcept.
Otherwise, don't move it.


The standard-library already has to do that in many places, and thankfully it is available to the public as std::move_if_noexcept() analogous to std::move.

I suggest adding your own helper which does that for iterators.
You know, it's itching in my fingers to modify merge() to use the conditional operator. Especially after applying the above point, which makes the common part even bigger.
One of the advantages moveing is that it allows for guaranteed success in more cases. Yes, writing flexible and comprehensive noexcept-specifications can be a pain, but your callers will thank you.

Without doing that work, a good part of the advantage of the two-range version is lost.
I would suggest renaming your iterator-ranges source and target respectively, neither is properly scratch. Also, I would use the more common temp as a name in merge_sort(begin, end).
Are you aware of the sordid tale that is std::vector&lt;bool&gt;?
I'm not saying it won't work in this case, though slowly.
You do know that C++17 has class template argument deduction?
It's nice to see that you only use &lt; for comparisons, just like the standard-library. That should enable you to easily modify your code to allow for a custom comparison-object.
But there is a problem in how you do the comparisons, as your merge() is needlessly not stable: If both are equal, you should take from the left range instead.
Consider asserting that the two iterator-types fit together in the function, or testing it for SFINAE outside.