You could rebase branches B and C individually and then use grafts (or git-replace) to re-attach the new rebased branches to the merge commit. using grafts I would do
# rebase the individual branches
git rebase M B2 --onto A
git rebase M C2 --onto A
# replace old branch heads with rebased branch heads
echo $(git rev-parse D1) $(git rev-parse B2') $(git rev-parse C2') > .git/info/grafts
The grafts will make your git history appear as if D1 has parents B2' and C2'. If you remove .git/info/grafts, D1 will have its original parents again.
To make this permanent, use filter branch to rewrite your history:
#make it permanent
git filter-branch -f --tag-name-filter cat D1'
A more elaborate explanation can be found in this answer on prepending the past to a git repository. It also explains how you should use git replace instead of grafts. I gave the example with grafts because I have a bit more experience with those.
git replace would rather be along the lines:
# rebase the individual branches
git rebase M B2 --onto A
git rebase M C2 --onto A
# replace old branch heads with rebased branch heads
git replace B2 B2'
git replace C2 C2'
#make it permanent
git filter-branch -f --tag-name-filter cat D1'