diff --git a/cms/djangoapps/contentstore/management/commands/reset_course_content.py b/cms/djangoapps/contentstore/management/commands/reset_course_content.py
new file mode 100644
index 0000000000000000000000000000000000000000..747acba8bf8fbbad24dd74b5bd0898ca6f0e342b
--- /dev/null
+++ b/cms/djangoapps/contentstore/management/commands/reset_course_content.py
@@ -0,0 +1,62 @@
+"""
+Django management command to reset the content of a course to a a different
+version, as specified by an ObjectId from the DraftVersioningModulestore (aka Split).
+"""
+from textwrap import dedent
+
+from django.core.management import BaseCommand, CommandError
+from opaque_keys.edx.keys import CourseKey
+
+from xmodule.modulestore import ModuleStoreEnum
+from xmodule.modulestore.django import modulestore
+
+
+class Command(BaseCommand):
+    """
+    Reset the content of a course run to a different version, and publish.
+
+    This is a powerful command; use with care.
+    It's analogous to `git reset --hard VERSION && git push -f`.
+
+    The intent of this is to restore overwritten course content that has not yet been
+    pruned from the modulestore. I guess you could use it to change a course's content
+    to any structure in Split you wanted, though.
+
+    Make sure you have validated the value of `course_id` and `version_guid`.
+    There is no confirmation prompt.
+
+    Example:
+
+        ./manage.py reset_course_content "course-v1:my+cool+course" "5fb5772e2fe4c7c76493c241"
+    """
+    help = dedent(__doc__)
+
+    def add_arguments(self, parser):
+        parser.add_argument(
+            'course_id',
+            help="A split-modulestore course key string (ie, course-v1:ORG+COURSE+RUN)",
+        )
+        parser.add_argument(
+            'version_guid',
+            help="A split-modulestore structure ObjectId (a 24-digit hex string)",
+        )
+
+    def handle(self, *args, **options):
+        course_key = CourseKey.from_string(options["course_id"])
+
+        version_guid = options["version_guid"]
+        unparseable_guid = False
+        try:
+            int(version_guid, 16)
+        except ValueError:
+            unparseable_guid = True
+        if unparseable_guid or len(version_guid) != 24:
+            raise CommandError("version_guid should be a 24-digit hexadecimal number")
+
+        print("Resetting '{}' to version '{}'...".format(course_key, version_guid))
+        modulestore().reset_course_to_version(
+            course_key,
+            version_guid,
+            ModuleStoreEnum.UserID.mgmt_command,
+        )
+        print("Done.")
diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_reset_course_content.py b/cms/djangoapps/contentstore/management/commands/tests/test_reset_course_content.py
new file mode 100644
index 0000000000000000000000000000000000000000..e731984c4dfdb8bb0fadcd78965121d9019de6e8
--- /dev/null
+++ b/cms/djangoapps/contentstore/management/commands/tests/test_reset_course_content.py
@@ -0,0 +1,42 @@
+"""
+Shallow tests for `./manage.py cms reset_course_content COURSE_KEY VERSION_GUID`
+"""
+import mock
+
+from django.test import TestCase
+from django.core.management import CommandError, call_command
+from opaque_keys import InvalidKeyError
+from opaque_keys.edx.keys import CourseKey
+
+from xmodule.modulestore import ModuleStoreEnum
+from xmodule.modulestore.mixed import MixedModuleStore
+
+
+class TestCommand(TestCase):
+    """
+    Shallow test for CMS `reset_course_content` management command.
+
+    The underlying implementation (`DraftVersioningModulestore.reset_course_to_version`)
+    is tested within the modulestore.
+    """
+
+    def test_bad_course_id(self):
+        with self.assertRaises(InvalidKeyError):
+            call_command("reset_course_content", "not_a_course_id", "0123456789abcdef01234567")
+
+    def test_wrong_length_version_guid(self):
+        with self.assertRaises(CommandError):
+            call_command("reset_course_content", "course-v1:a+b+c", "0123456789abcdef")
+
+    def test_non_hex_version_guid(self):
+        with self.assertRaises(CommandError):
+            call_command("reset_course_content", "course-v1:a+b+c", "0123456789abcdefghijklmn")
+
+    @mock.patch.object(MixedModuleStore, "reset_course_to_version")
+    def test_good_arguments(self, mock_reset_course_to_version):
+        call_command("reset_course_content", "course-v1:a+b+c", "0123456789abcdef01234567")
+        mock_reset_course_to_version.assert_called_once_with(
+            CourseKey.from_string("course-v1:a+b+c"),
+            "0123456789abcdef01234567",
+            ModuleStoreEnum.UserID.mgmt_command,
+        )
diff --git a/common/lib/xmodule/xmodule/modulestore/mixed.py b/common/lib/xmodule/xmodule/modulestore/mixed.py
index 6297888c6d35cacef2bc1e9813b5b0eb95a99582..0abfc1f251e1a005df9b0524b20691e32d1339ec 100644
--- a/common/lib/xmodule/xmodule/modulestore/mixed.py
+++ b/common/lib/xmodule/xmodule/modulestore/mixed.py
@@ -826,6 +826,19 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
         store = self._verify_modulestore_support(location.course_key, 'revert_to_published')
         return store.revert_to_published(location, user_id)
 
+    def reset_course_to_version(self, course_key, version_guid, user_id):
+        """
+        Resets the content of a course at `course_key` to a version specified by `version_guid`.
+
+        :raises NotImplementedError: if not supported by store.
+        """
+        store = self._verify_modulestore_support(course_key, 'reset_course_to_version')
+        return store.reset_course_to_version(
+            course_key=course_key,
+            version_guid=version_guid,
+            user_id=user_id,
+        )
+
     def close_all_connections(self):
         """
         Close all db connections
diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
index cfa85d27c96469e6ed76e3e56fe834d94af7421d..1a273059263e2e59befd5126183932cb7aa60f6b 100644
--- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
+++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
@@ -461,6 +461,20 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli
             if index_entry is not None:
                 self._update_head(draft_course_key, index_entry, ModuleStoreEnum.BranchName.draft, new_structure['_id'])
 
+    def reset_course_to_version(self, course_key, version_guid, user_id):
+        """
+        Resets a course to a version specified by the string `version_guid`.
+
+        The `version_guid` refers to the Mongo-level id ("_id")
+        of the structure we want to revert to. It should be a 24-digit hex string.
+        """
+        draft_course_key = course_key.for_branch(ModuleStoreEnum.BranchName.draft)
+        version_object_id = course_key.as_object_id(version_guid)
+        with self.bulk_operations(draft_course_key):
+            index_entry = self._get_index_if_valid(draft_course_key)
+            self._update_head(draft_course_key, index_entry, ModuleStoreEnum.BranchName.draft, version_object_id)
+            self.force_publish_course(draft_course_key, user_id, commit=True)
+
     def update_parent_if_moved(self, item_location, original_parent_location, course_structure, user_id):
         """
         Update parent of an item if it has moved.
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
index d023e5c99a248ced1fdcf3541b17513af6d076d1..1e32991e1374b31d5c931f20282ad9c42119c65d 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
@@ -47,6 +47,7 @@ from xmodule.modulestore.exceptions import (
 from xmodule.modulestore.inheritance import InheritanceMixin
 from xmodule.modulestore.mixed import MixedModuleStore
 from xmodule.modulestore.search import navigation_index, path_to_location
+from xmodule.modulestore.split_mongo.split import SplitMongoModuleStore
 from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES
 from xmodule.modulestore.tests.factories import check_exact_number_of_calls, check_mongo_calls, mongo_uses_error_check
 from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM
@@ -1796,6 +1797,96 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
         # It does not discard the child vertical, even though that child is a draft (with no published version)
         self.assertEqual(num_children, len(reverted_parent.children))
 
+    def test_reset_course_to_version(self):
+        """
+        Test calling `DraftVersioningModuleStore.test_reset_course_to_version`.
+        """
+        # Set up test course.
+        self.initdb(ModuleStoreEnum.Type.split)  # Old Mongo does not support this operation.
+        self._create_block_hierarchy()
+        self.store.publish(self.course.location, self.user_id)
+
+        # Get children of a vertical as a set.
+        # We will use this set as a basis for content comparision in this test.
+        original_vertical = self.store.get_item(self.vertical_x1a)
+        original_vertical_children = set(original_vertical.children)
+
+        # Find the version_guid of our course by diving into Split Mongo.
+        split = self._get_split_modulestore()
+        course_index = split.get_course_index(self.course.location.course_key)
+        original_version_guid = course_index["versions"]["published-branch"]
+
+        # Reset course to currently-published version.
+        # This should be a no-op.
+        self.store.reset_course_to_version(
+            self.course.location.course_key,
+            original_version_guid,
+            self.user_id,
+        )
+        noop_reset_vertical = self.store.get_item(self.vertical_x1a)
+        assert set(noop_reset_vertical.children) == original_vertical_children
+
+        # Delete a problem from the vertical and publish.
+        # Vertical should have one less problem than before.
+        self.store.delete_item(self.problem_x1a_1, self.user_id)
+        self.store.publish(self.course.location, self.user_id)
+        modified_vertical = self.store.get_item(self.vertical_x1a)
+        assert set(modified_vertical.children) == (
+            original_vertical_children - {self.problem_x1a_1}
+        )
+
+        # Add a couple more children to the vertical.
+        # and publish a couple more times.
+        # We want to make sure we can restore from something a few versions back.
+        self.store.create_child(
+            self.user_id,
+            self.vertical_x1a,
+            'problem',
+            block_id='new_child1',
+        )
+        self.store.publish(self.course.location, self.user_id)
+        self.store.create_child(
+            self.user_id,
+            self.vertical_x1a,
+            'problem',
+            block_id='new_child2',
+        )
+        self.store.publish(self.course.location, self.user_id)
+
+        # Add another child, but don't publish.
+        # We want to make sure that this works with a dirty draft branch.
+        self.store.create_child(
+            self.user_id,
+            self.vertical_x1a,
+            'problem',
+            block_id='new_child3',
+        )
+
+        # Reset course to original version.
+        # The restored vertical should have the same children as it did originally.
+        self.store.reset_course_to_version(
+            self.course.location.course_key,
+            original_version_guid,
+            self.user_id,
+        )
+        restored_vertical = self.store.get_item(self.vertical_x1a)
+        assert set(restored_vertical.children) == original_vertical_children
+
+    def _get_split_modulestore(self):
+        """
+        Grab the SplitMongo modulestore instance from within the Mixed modulestore.
+
+        Assumption: There is a SplitMongo modulestore within the Mixed modulestore.
+        This assumpion is hacky, but it seems OK because we're removing the
+        Old (non-Split) Mongo modulestores soon.
+
+        Returns: SplitMongoModuleStore
+        """
+        for store in self.store.modulestores:
+            if isinstance(store, SplitMongoModuleStore):
+                return store
+        assert False, "SplitMongoModuleStore was not found in MixedModuleStore"
+
     # Draft: get all items which can be or should have parents
     # Split: active_versions, structure
     @ddt.data((ModuleStoreEnum.Type.mongo, 1, 0), (ModuleStoreEnum.Type.split, 2, 0))