diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index 89b83cf..44c98e2 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -161,6 +161,13 @@ class EntityType implements EntityTypeInterface {
   protected $revision_table = NULL;
 
   /**
+   * An array of entity metadata fields.
+   *
+   * @var array
+   */
+  protected $revision_fields = [];
+
+  /**
    * The name of the entity type's data table.
    *
    * @var string|null
@@ -384,6 +391,29 @@ public function hasKey($key) {
   /**
    * {@inheritdoc}
    */
+  public function getRevisionFields() {
+    return $this->revision_fields;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRevisionField($field) {
+    $keys = $this->getRevisionFields();
+    return isset($keys[$field]) ? $keys[$field] : FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasRevisionField($field) {
+    $keys = $this->getRevisionFields();
+    return !empty($keys[$field]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function id() {
     return $this->id;
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
index c6336c9..847a66b 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
@@ -133,6 +133,45 @@ public function getKey($key);
   public function hasKey($key);
 
   /**
+   * Gets an array of entity revision metadata fields.
+   *
+   * @return array
+   *   An array describing how the Field API can extract revision metadata
+   *   information of this entity type:
+   *   - revision_log_message: The name of the property that contains description
+   *     of the changes that were made in the current revision.
+   *   - revision_user: The name of the property that contains the user ID of
+   *     the author of the current revision.
+   *   - revision_created: The name of the property that contains the timestamp
+   *     of the current revision.
+   */
+  public function getRevisionFields();
+
+  /**
+   * Gets a specific entity revision metadata field.
+   *
+   * @param string $key
+   *   The name of the entity revision metadata field to return.
+   *
+   * @return string|bool
+   *   The entity revision metadata field, or FALSE if it does not exist.
+   *
+   * @see self::getRevisionFields()
+   */
+  public function getRevisionField($field);
+
+  /**
+   * Indicates if a given entity revision metadata field exists.
+   *
+   * @param string $key
+   *   The name of the entity revision metadata field to check.
+   *
+   * @return bool
+   *   TRUE if a given entity revision metadata field exists, FALSE otherwise.
+   */
+  public function hasRevisionField($field);
+
+  /**
    * Indicates whether entities should be statically cached.
    *
    * @return bool
diff --git a/core/lib/Drupal/Core/Entity/RevisionLogEntityTrait.php b/core/lib/Drupal/Core/Entity/RevisionLogEntityTrait.php
index 7392858..d6f4787 100644
--- a/core/lib/Drupal/Core/Entity/RevisionLogEntityTrait.php
+++ b/core/lib/Drupal/Core/Entity/RevisionLogEntityTrait.php
@@ -25,30 +25,34 @@
    * @see \Drupal\Core\Entity\FieldableEntityInterface::baseFieldDefinitions()
    */
   public static function revisionLogBaseFieldDefinitions(EntityTypeInterface $entity_type) {
-    $fields['revision_created'] = BaseFieldDefinition::create('created')
-      ->setLabel(t('Revision create time'))
-      ->setDescription(t('The time that the current revision was created.'))
-      ->setRevisionable(TRUE);
-
-    $fields['revision_user'] = BaseFieldDefinition::create('entity_reference')
-      ->setLabel(t('Revision user'))
-      ->setDescription(t('The user ID of the author of the current revision.'))
-      ->setSetting('target_type', 'user')
-      ->setRevisionable(TRUE);
-
-    $fields['revision_log_message'] = BaseFieldDefinition::create('string_long')
-      ->setLabel(t('Revision log message'))
-      ->setDescription(t('Briefly describe the changes you have made.'))
-      ->setRevisionable(TRUE)
-      ->setDefaultValue('')
-      ->setDisplayOptions('form', [
-        'type' => 'string_textarea',
-        'weight' => 25,
-        'settings' => [
-          'rows' => 4,
-        ],
-      ]);
-
+    $fields = [];
+    if ($entity_type->hasRevisionField('revision_created')) {
+      $fields[$entity_type->getRevisionField('revision_created')] = BaseFieldDefinition::create('created')
+        ->setLabel(t('Revision create time'))
+        ->setDescription(t('The time that the current revision was created.'))
+        ->setRevisionable(TRUE);
+    }
+    if ($entity_type->hasRevisionField('revision_user')) {
+      $fields[$entity_type->getRevisionField('revision_user')] = BaseFieldDefinition::create('entity_reference')
+        ->setLabel(t('Revision user'))
+        ->setDescription(t('The user ID of the author of the current revision.'))
+        ->setSetting('target_type', 'user')
+        ->setRevisionable(TRUE);
+    }
+    if ($entity_type->hasRevisionField('revision_log_message')) {
+      $fields[$entity_type->getRevisionField('revision_log_message')] = BaseFieldDefinition::create('string_long')
+        ->setLabel(t('Revision log message'))
+        ->setDescription(t('Briefly describe the changes you have made.'))
+        ->setRevisionable(TRUE)
+        ->setDefaultValue('')
+        ->setDisplayOptions('form', [
+          'type' => 'string_textarea',
+          'weight' => 25,
+          'settings' => [
+            'rows' => 4,
+          ],
+        ]);
+    }
     return $fields;
   }
 
@@ -56,14 +60,16 @@ public static function revisionLogBaseFieldDefinitions(EntityTypeInterface $enti
    * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionCreationTime().
    */
   public function getRevisionCreationTime() {
-    return $this->revision_created->value;
+    $field = $this->getEntityType()->getRevisionField('revision_created');
+    return $this->{$field}->value;
   }
 
   /**
    * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionCreationTime().
    */
   public function setRevisionCreationTime($timestamp) {
-    $this->revision_created->value = $timestamp;
+    $field = $this->getEntityType()->getRevisionField('revision_created');
+    $this->{$field}->value = $timestamp;
     return $this;
   }
 
@@ -71,14 +77,16 @@ public function setRevisionCreationTime($timestamp) {
    * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionUser().
    */
   public function getRevisionUser() {
-    return $this->revision_user->entity;
+    $field = $this->getEntityType()->getRevisionField('revision_user');
+    return $this->{$field}->entity;
   }
 
   /**
    * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionUser().
    */
   public function setRevisionUser(UserInterface $account) {
-    $this->revision_user->entity = $account;
+    $field = $this->getEntityType()->getRevisionField('revision_user');
+    $this->{$field}->entity = $account;
     return $this;
   }
 
@@ -86,14 +94,16 @@ public function setRevisionUser(UserInterface $account) {
    * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionUserId().
    */
   public function getRevisionUserId() {
-    return $this->revision_user->target_id;
+    $field = $this->getEntityType()->getRevisionField('revision_user');
+    return $this->{$field}->target_id;
   }
 
   /**
    * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionUserId().
    */
   public function setRevisionUserId($user_id) {
-    $this->revision_user->target_id = $user_id;
+    $field = $this->getEntityType()->getRevisionField('revision_user');
+    $this->{$field}->target_id = $user_id;
     return $this;
   }
 
@@ -101,14 +111,16 @@ public function setRevisionUserId($user_id) {
    * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionLogMessage().
    */
   public function getRevisionLogMessage() {
-    return $this->revision_log_message->value;
+    $field = $this->getEntityType()->getRevisionField('revision_log_message');
+    return $this->{$field}->value;
   }
 
   /**
    * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionLogMessage().
    */
   public function setRevisionLogMessage($revision_log_message) {
-    $this->revision_log_message->value = $revision_log_message;
+    $field = $this->getEntityType()->getRevisionField('revision_log_message');
+    $this->{$field}->value = $revision_log_message;
     return $this;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 2ea450d..f2f4afd 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -294,17 +294,14 @@ public function getTableMapping(array $storage_definitions = NULL) {
       // Make sure the key fields come first in the list of fields.
       $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields));
 
-      // Nodes have all three of these fields, while custom blocks only have
-      // log.
-      // @todo Provide automatic definitions for revision metadata fields in
-      //   https://www.drupal.org/node/2248983.
-      $revision_metadata_fields = array_intersect(array(
-        'revision_timestamp',
-        'revision_uid',
-        'revision_log',
-      ), $all_fields);
-
+      // If the entity is revisionable, gather the fields that need to be put
+      // in the revision table.
       $revisionable = $this->entityType->isRevisionable();
+      if ($revisionable) {
+        $revision_fields = $this->entityType->getRevisionFields();
+        $revision_metadata_fields = array_intersect(array_values($revision_fields), $all_fields);
+      }
+
       $translatable = $this->entityType->isTranslatable();
       if (!$revisionable && !$translatable) {
         // The base layout stores all the base field values in the base table.
diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php
index 13af342..0bd3c99 100644
--- a/core/modules/block_content/src/Entity/BlockContent.php
+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -50,6 +50,11 @@
  *     "langcode" = "langcode",
  *     "uuid" = "uuid"
  *   },
+ *   revision_fields = {
+ *     "revision_user" = "revision_user",
+ *     "revision_created" = "revision_created",
+ *     "revision_log_message" = "revision_log"
+ *   },
  *   bundle_entity_type = "block_content_type",
  *   field_ui_base_route = "entity.block_content_type.edit_form",
  *   render_cache = FALSE,
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index bdb8050..cfbc00e 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -57,6 +57,11 @@
  *     "status" = "status",
  *     "uid" = "uid",
  *   },
+ *   revision_fields = {
+ *     "revision_user" = "revision_uid",
+ *     "revision_created" = "revision_timestamp",
+ *     "revision_log_message" = "revision_log"
+ *   },
  *   bundle_entity_type = "node_type",
  *   field_ui_base_route = "entity.node_type.edit_form",
  *   common_reference_target = TRUE,
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 3ef24a5..f9fe50e 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1730,3 +1730,76 @@ function system_update_8201() {
 /**
  * @} End of "addtogroup updates-8.2.0".
  */
+
+/**
+ * @addtogroup updates-8.3.0
+ * @{
+ */
+
+/**
+ * Move revision metadata fields from the data tables to the revision table.
+ *
+ * Due to the fields from RevisionLogEntityTrait not being explicitly mentioned
+ * in the storage they might have been installed wrongly in the data tables for
+ * revisionable and translatable entities.
+ */
+function system_update_8300(&$sandbox) {
+  static $revisions = NULL;
+  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
+  $database = \Drupal::database();
+  $database_schema = $database->schema();
+  $revision_metadata_fields_to_update = array_flip([
+    'revision_created',
+    'revision_user',
+    'revision_log_message'
+  ]);
+  foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type_id => $entity_type) {
+    if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
+      $class = $entity_type->getClass();
+      $base_fields = $class::baseFieldDefinitions($entity_type);
+      $fields_to_update = array_intersect_key($base_fields, $revision_metadata_fields_to_update);
+
+      if (!empty($fields_to_update)) {
+        $data_table = $entity_type->getDataTable() ?: $entity_type_id . '_field_data';
+        $revision_data_table = $entity_type->getRevisionDataTable() ?: $entity_type_id . '_field_revision';
+        $revision_table = $entity_type->getRevisionTable() ?: $entity_type_id . '_revision';
+        $revision_field = $entity_type->getKey('revision');
+
+        foreach ($fields_to_update as $field_name => $definition) {
+          // Ensure the field is present in the data tables.
+          if ($database_schema->fieldExists($data_table, $field_name) && $database_schema->fieldExists($revision_data_table, $field_name)) {
+            // Install the field in the revision table.
+            $entity_definition_update_manager->installFieldStorageDefinition($field_name, $entity_type_id, $entity_type->getProvider(), $definition);
+
+            // Collect the revision ids only once for an entity type.
+            $revisions = isset($revisions) ? $revisions : \Drupal::entityQuery($entity_type_id)
+              ->allRevisions()
+              ->execute();
+
+            // Apply the field value from the revision data table to the
+            // revision table.
+            foreach ($revisions as $rev_id => $id) {
+              $field_value = $database->select($revision_data_table, 'rd')
+                ->fields('rd', [$field_name])
+                ->condition($revision_field, $rev_id)
+                ->execute()
+                ->fetchField();
+              $database->update($revision_table)
+                ->condition($revision_field, $rev_id)
+                ->fields([$field_name => $field_value])
+                ->execute();
+            }
+            // Drop the field from the data tables.
+            $database_schema->dropField($data_table, $field_name);
+            $database_schema->dropField($revision_data_table, $field_name);
+          }
+        }
+        $revisions = NULL;
+      }
+    }
+  }
+}
+
+/**
+ * @} End of "addtogroup updates-8.3.0".
+ */
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithRevisionLog.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithRevisionLog.php
index 4f4f4f1..d9e7c06 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithRevisionLog.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithRevisionLog.php
@@ -35,6 +35,11 @@
  *     "label" = "name",
  *     "langcode" = "langcode",
  *   },
+ *   revision_fields = {
+ *     "revision_user" = "revision_uid",
+ *     "revision_created" = "revision_timestamp",
+ *     "revision_log_message" = "revision_log"
+ *   },
  *   links = {
  *     "canonical" = "/entity_test_revlog/manage/{entity_test_revlog}",
  *     "delete-form" = "/entity_test/delete/entity_test_revlog/{entity_test_revlog}",
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
index 56b4b00..099c331 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
@@ -533,6 +533,9 @@ public function testGetTableMappingRevisionable(array $entity_keys) {
         array('bundle', $entity_keys['bundle']),
         array('revision', $entity_keys['revision']),
       )));
+    $this->entityType->expects($this->any())
+      ->method('getRevisionFields')
+      ->will($this->returnValue([]));
 
     $this->setUpEntityStorage();
 
@@ -573,13 +576,13 @@ public function testGetTableMappingRevisionableWithFields(array $entity_keys) {
     // PHPUnit does not allow for multiple data providers.
     $test_cases = array(
       array(),
-      array('revision_timestamp'),
-      array('revision_uid'),
-      array('revision_log'),
-      array('revision_timestamp', 'revision_uid'),
-      array('revision_timestamp', 'revision_log'),
-      array('revision_uid', 'revision_log'),
-      array('revision_timestamp', 'revision_uid', 'revision_log'),
+      array('revision_created' => 'revision_timestamp'),
+      array('revision_user' => 'revision_uid'),
+      array('revision_log_message' => 'revision_log'),
+      array('revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid'),
+      array('revision_created' => 'revision_timestamp', 'revision_log_message' => 'revision_log'),
+      array('revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'),
+      array('revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'),
     );
     foreach ($test_cases as $revision_metadata_field_names) {
       $this->setUp();
@@ -604,6 +607,10 @@ public function testGetTableMappingRevisionableWithFields(array $entity_keys) {
           array('revision', $entity_keys['revision']),
         )));
 
+      $this->entityType->expects($this->any())
+        ->method('getRevisionFields')
+        ->will($this->returnValue($revision_metadata_field_names));
+
       $this->setUpEntityStorage();
 
       $mapping = $this->entityStorage->getTableMapping();
@@ -760,6 +767,11 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys)
       'uuid' => $entity_keys['uuid'],
       'langcode' => 'langcode',
     );
+    $revision_fields = array(
+      'revision_created' => 'revision_timestamp',
+      'revision_user' => 'revision_uid',
+      'revision_log_message' => 'revision_log'
+    );
 
     $this->entityType->expects($this->atLeastOnce())
       ->method('isRevisionable')
@@ -779,6 +791,9 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys)
         array('revision', $entity_keys['revision']),
         array('langcode', $entity_keys['langcode']),
       )));
+    $this->entityType->expects($this->any())
+      ->method('getRevisionFields')
+      ->will($this->returnValue($revision_fields));
 
     $this->setUpEntityStorage();
 
@@ -864,13 +879,13 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent
     // PHPUnit does not allow for multiple data providers.
     $test_cases = array(
       array(),
-      array('revision_timestamp'),
-      array('revision_uid'),
-      array('revision_log'),
-      array('revision_timestamp', 'revision_uid'),
-      array('revision_timestamp', 'revision_log'),
-      array('revision_uid', 'revision_log'),
-      array('revision_timestamp', 'revision_uid', 'revision_log'),
+      array('revision_created' => 'revision_timestamp'),
+      array('revision_user' => 'revision_uid'),
+      array('revision_log_message' => 'revision_log'),
+      array('revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid'),
+      array('revision_created' => 'revision_timestamp', 'revision_log_message' => 'revision_log'),
+      array('revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'),
+      array('revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'),
     );
     foreach ($test_cases as $revision_metadata_field_names) {
       $this->setUp();
@@ -900,6 +915,9 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent
           array('revision', $entity_keys['revision']),
           array('langcode', $entity_keys['langcode']),
         )));
+      $this->entityType->expects($this->any())
+        ->method('getRevisionFields')
+        ->will($this->returnValue($revision_metadata_field_names));
 
       $this->setUpEntityStorage();
 
