This answer assumes you either haven't pushed master or you're the only person working on the project (in which case it doesn't really matter). If you have pushed master and someone else pulled your changes, you'll need to communicate with them to make sure they update their repositories appropriately.
# Assuming you're on master
git branch <feature> <D> # Create a branch named <feature> at commit <D>
git rebase --onto <B> <D> master # Transplant branch
Git rebase documentation has a pretty good graphical explanation of what rebase --onto
does.
If you want to avoid a rebase
altogether, you should be able to do
git branch <feature> <D> # Create a branch named <feature> at commit <D>
git revert <D> # undo D
git revert <C> # undo C
This will result in a history like this
A-B-C-D-E-F-G-!D-!C
^ ^
feature master
Anyone who checks out master, will see code as if commits C and D never happened, you'll just have a couple of reverts in your history. That's the preferred way of backing changes out of a branch that has been pushed.