diff --git a/core/modules/block_content/src/BlockContentViewsData.php b/core/modules/block_content/src/BlockContentViewsData.php
index aa23a534f84944070d0abf294d810b6d346c9de1..06c9de77f2286dcb4329bf4633f761903a029fe9 100644
--- a/core/modules/block_content/src/BlockContentViewsData.php
+++ b/core/modules/block_content/src/BlockContentViewsData.php
@@ -36,27 +36,6 @@ public function getViewsData() {
     $data['block_content_field_revision']['table']['base']['help'] = $this->t('Block Content revision is a history of changes to block content.');
     $data['block_content_field_revision']['table']['base']['defaults']['title'] = 'info';
 
-    // @todo EntityViewsData should add these relationships by default.
-    //   https://www.drupal.org/node/2410275
-    $data['block_content_field_revision']['id']['relationship']['id'] = 'standard';
-    $data['block_content_field_revision']['id']['relationship']['base'] = 'block_content_field_data';
-    $data['block_content_field_revision']['id']['relationship']['base field'] = 'id';
-    $data['block_content_field_revision']['id']['relationship']['title'] = $this->t('Block Content');
-    $data['block_content_field_revision']['id']['relationship']['label'] = $this->t('Get the actual block content from a block content revision.');
-
-    $data['block_content_field_revision']['revision_id']['relationship']['id'] = 'standard';
-    $data['block_content_field_revision']['revision_id']['relationship']['base'] = 'block_content_field_data';
-    $data['block_content_field_revision']['revision_id']['relationship']['base field'] = 'revision_id';
-    $data['block_content_field_revision']['revision_id']['relationship']['title'] = $this->t('Block Content');
-    $data['block_content_field_revision']['revision_id']['relationship']['label'] = $this->t('Get the actual block content from a block content revision.');
-
-    $data['block_content_revision']['revision_user']['help'] = $this->t('The user who created the revision.');
-    $data['block_content_revision']['revision_user']['relationship']['label'] = $this->t('revision user');
-    $data['block_content_revision']['revision_user']['filter']['id'] = 'user_name';
-
-    $data['block_content_revision']['table']['join']['block_content_field_data']['left_field'] = 'revision_id';
-    $data['block_content_revision']['table']['join']['block_content_field_data']['field'] = 'revision_id';
-
     return $data;
   }
 
diff --git a/core/modules/media/src/MediaViewsData.php b/core/modules/media/src/MediaViewsData.php
index 2dc16496866b28b736917814fbe85afe7f1c50bf..393548be84c6c94ce6118ee6d62a842e0db64b60 100644
--- a/core/modules/media/src/MediaViewsData.php
+++ b/core/modules/media/src/MediaViewsData.php
@@ -18,13 +18,6 @@ public function getViewsData() {
     $data['media_field_data']['table']['wizard_id'] = 'media';
     $data['media_field_revision']['table']['wizard_id'] = 'media_revision';
 
-    $data['media_revision']['revision_user']['help'] = $this->t('The user who created the revision.');
-    $data['media_revision']['revision_user']['relationship']['label'] = $this->t('revision user');
-    $data['media_revision']['revision_user']['filter']['id'] = 'user_name';
-
-    $data['media_revision']['table']['join']['media_field_data']['left_field'] = 'vid';
-    $data['media_revision']['table']['join']['media_field_data']['field'] = 'vid';
-
     $data['media_field_data']['status_extra'] = [
       'title' => $this->t('Published status or admin user'),
       'help' => $this->t('Filters out unpublished media if the current user cannot view it.'),
diff --git a/core/modules/node/src/NodeViewsData.php b/core/modules/node/src/NodeViewsData.php
index 32aa04c725dfc1fcbb7c14505ee6f0f7c03ffcb5..5c1d34cc74d330ccfed4e47125300434df3edd04 100644
--- a/core/modules/node/src/NodeViewsData.php
+++ b/core/modules/node/src/NodeViewsData.php
@@ -178,12 +178,6 @@ public function getViewsData() {
       ],
     ];
 
-    $data['node_field_data']['uid']['help'] = $this->t('The user authoring the content. If you need more fields than the uid add the content: author relationship');
-    $data['node_field_data']['uid']['filter']['id'] = 'user_name';
-    $data['node_field_data']['uid']['relationship']['title'] = $this->t('Content author');
-    $data['node_field_data']['uid']['relationship']['help'] = $this->t('Relate content to the user who created it.');
-    $data['node_field_data']['uid']['relationship']['label'] = $this->t('author');
-
     $data['node']['node_listing_empty'] = [
       'title' => $this->t('Empty Node Frontpage behavior'),
       'help' => $this->t('Provides a link to the node add overview page.'),
@@ -211,45 +205,15 @@ public function getViewsData() {
     // @todo the NID field needs different behavior on revision/non-revision
     //   tables. It would be neat if this could be encoded in the base field
     //   definition.
-    $data['node_field_revision']['nid']['relationship']['id'] = 'standard';
-    $data['node_field_revision']['nid']['relationship']['base'] = 'node_field_data';
-    $data['node_field_revision']['nid']['relationship']['base field'] = 'nid';
-    $data['node_field_revision']['nid']['relationship']['title'] = $this->t('Content');
-    $data['node_field_revision']['nid']['relationship']['label'] = $this->t('Get the actual content from a content revision.');
-    $data['node_field_revision']['nid']['relationship']['extra'][] = [
-      'field' => 'langcode',
-      'left_field' => 'langcode',
-    ];
-
     $data['node_field_revision']['vid'] = [
       'argument' => [
         'id' => 'node_vid',
         'numeric' => TRUE,
       ],
-      'relationship' => [
-        'id' => 'standard',
-        'base' => 'node_field_data',
-        'base field' => 'vid',
-        'title' => $this->t('Content'),
-        'label' => $this->t('Get the actual content from a content revision.'),
-        'extra' => [
-          [
-            'field' => 'langcode',
-            'left_field' => 'langcode',
-          ],
-        ],
-      ],
     ] + $data['node_field_revision']['vid'];
 
     $data['node_field_revision']['langcode']['help'] = $this->t('The language the original content is in.');
 
-    $data['node_revision']['revision_uid']['help'] = $this->t('The user who created the revision.');
-    $data['node_revision']['revision_uid']['relationship']['label'] = $this->t('revision user');
-    $data['node_revision']['revision_uid']['filter']['id'] = 'user_name';
-
-    $data['node_revision']['table']['join']['node_field_data']['left_field'] = 'vid';
-    $data['node_revision']['table']['join']['node_field_data']['field'] = 'vid';
-
     $data['node_field_revision']['table']['wizard_id'] = 'node_field_revision';
 
     $data['node_field_revision']['status']['filter']['label'] = $this->t('Published');
diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index 87bfa116b3c5e681a544cd6de85804e23f547e36..2ae740d41bc87590ab0cc664f321b4f3ff17d7e3 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\views;
 
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\ContentEntityType;
 use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Entity\EntityHandlerInterface;
@@ -132,7 +133,8 @@ public function getViewsData() {
     $base_table = $this->entityType->getBaseTable() ?: $this->entityType->id();
     $views_revision_base_table = NULL;
     $revisionable = $this->entityType->isRevisionable();
-    $base_field = $this->entityType->getKey('id');
+    $entity_id_key = $this->entityType->getKey('id');
+    $entity_keys = $this->entityType->getKeys();
 
     $revision_table = '';
     if ($revisionable) {
@@ -153,7 +155,8 @@ public function getViewsData() {
     if ($revisionable && $translatable) {
       $revision_data_table = $this->entityType->getRevisionDataTable() ?: $this->entityType->id() . '_field_revision';
     }
-    $revision_field = $this->entityType->getKey('revision');
+    $entity_revision_key = $this->entityType->getKey('revision');
+    $revision_field = $entity_revision_key;
 
     // Setup base information of the views data.
     $data[$base_table]['table']['group'] = $this->entityType->getLabel();
@@ -164,7 +167,7 @@ public function getViewsData() {
       $views_base_table = $data_table;
     }
     $data[$views_base_table]['table']['base'] = [
-      'field' => $base_field,
+      'field' => $entity_id_key,
       'title' => $this->entityType->getLabel(),
       'cache_contexts' => $this->entityType->getListCacheContexts(),
       'access query tag' => $this->entityType->id() . '_access',
@@ -219,8 +222,8 @@ public function getViewsData() {
     // Setup relations to the revisions/property data.
     if ($data_table) {
       $data[$base_table]['table']['join'][$data_table] = [
-        'left_field' => $base_field,
-        'field' => $base_field,
+        'left_field' => $entity_id_key,
+        'field' => $entity_id_key,
         'type' => 'INNER',
       ];
       $data[$data_table]['table']['group'] = $this->entityType->getLabel();
@@ -271,6 +274,33 @@ public function getViewsData() {
           'filter' => ['id' => 'latest_translation_affected_revision'],
         ];
       }
+      // Add a relationship from the revision table back to the main table.
+      $entity_type_label = $this->entityType->getLabel();
+      $data[$views_revision_base_table][$entity_id_key]['relationship'] = [
+        'id' => 'standard',
+        'base' => $views_base_table,
+        'base field' => $entity_id_key,
+        'title' => $entity_type_label,
+        'help' => $this->t('Get the actual @label from a @label revision', ['@label' => $entity_type_label]),
+      ];
+      $data[$views_revision_base_table][$entity_revision_key]['relationship'] = [
+        'id' => 'standard',
+        'base' => $views_base_table,
+        'base field' => $entity_revision_key,
+        'title' => $this->t('@label revision', ['@label' => $entity_type_label]),
+        'help' => $this->t('Get the actual @label from a @label revision', ['@label' => $entity_type_label]),
+      ];
+      if ($translatable) {
+        $extra = [
+          'field' => $entity_keys['langcode'],
+          'left_field' => $entity_keys['langcode'],
+        ];
+        $data[$views_revision_base_table][$entity_id_key]['relationship']['extra'][] = $extra;
+        $data[$views_revision_base_table][$entity_revision_key]['relationship']['extra'][] = $extra;
+        $data[$revision_table]['table']['join'][$views_base_table]['left_field'] = $entity_revision_key;
+        $data[$revision_table]['table']['join'][$views_base_table]['field'] = $entity_revision_key;
+      }
+
     }
 
     $this->addEntityLinks($data[$base_table]);
@@ -285,7 +315,6 @@ public function getViewsData() {
     if ($table_mapping = $this->storage->getTableMapping($field_definitions)) {
       // Fetch all fields that can appear in both the base table and the data
       // table.
-      $entity_keys = $this->entityType->getKeys();
       $duplicate_fields = array_intersect_key($entity_keys, array_flip(['id', 'revision', 'bundle']));
       // Iterate over each table we have so far and collect field data for each.
       // Based on whether the field is in the field_definitions provided by the
@@ -312,7 +341,7 @@ public function getViewsData() {
           $data[$table]['table']['group'] = $this->entityType->getLabel();
           $data[$table]['table']['provider'] = $this->entityType->getProvider();
           $data[$table]['table']['join'][$views_base_table] = [
-            'left_field' => $base_field,
+            'left_field' => $entity_id_key,
             'field' => 'entity_id',
             'extra' => [
               ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
@@ -334,6 +363,12 @@ public function getViewsData() {
           }
         }
       }
+      if (($uid_key = $entity_keys['uid'] ?? '')) {
+        $data[$data_table][$uid_key]['filter']['id'] = 'user_name';
+      }
+      if ($revision_table && ($revision_uid_key = $this->entityType->getRevisionMetadataKeys()['revision_user'] ?? '')) {
+        $data[$revision_table][$revision_uid_key]['filter']['id'] = 'user_name';
+      }
     }
 
     // Add the entity type key to each table generated.
@@ -411,7 +446,10 @@ protected function mapFieldDefinition($table, $field_name, FieldDefinitionInterf
     //   mapSingleFieldViewsData() method does with $first.
     $first = TRUE;
     foreach ($field_column_mapping as $field_column_name => $schema_field_name) {
-      $table_data[$schema_field_name] = $this->mapSingleFieldViewsData($table, $field_name, $field_definition_type, $field_column_name, $field_schema['columns'][$field_column_name]['type'], $first, $field_definition);
+      // The fields might be defined before the actual table.
+      $table_data = $table_data ?: [];
+      $table_data += [$schema_field_name => []];
+      $table_data[$schema_field_name] = NestedArray::mergeDeep($table_data[$schema_field_name], $this->mapSingleFieldViewsData($table, $field_name, $field_definition_type, $field_column_name, $field_schema['columns'][$field_column_name]['type'], $first, $field_definition));
       $table_data[$schema_field_name]['entity field'] = $field_name;
       $first = FALSE;
     }
diff --git a/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php b/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php
index 372a4c4add80e1d4e608999eb4afd9e8fbfeb53a..c96792e93b085671d7e7421f48e994e2b18304a8 100644
--- a/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php
+++ b/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php
@@ -256,6 +256,11 @@ public function testRevisionTableWithoutDataTable() {
     $this->assertCount(1, $revision_data['table']['join']);
     $this->assertEquals(['entity_test' => ['left_field' => 'revision_id', 'field' => 'revision_id', 'type' => 'INNER']], $revision_data['table']['join']);
     $this->assertFalse(isset($data['data_table']));
+
+    $this->assertEquals('entity_test', $revision_data['id']['relationship']['base']);
+    $this->assertEquals('id', $revision_data['id']['relationship']['base field']);
+    $this->assertEquals('entity_test', $revision_data['revision_id']['relationship']['base']);
+    $this->assertEquals('revision_id', $revision_data['revision_id']['relationship']['base field']);
   }
 
   /**
@@ -294,16 +299,25 @@ public function testRevisionTableWithRevisionDataTableAndDataTable() {
     ], $revision_field_data['table']['join']);
 
     $revision_base_data = $data['entity_test_mulrev_revision'];
-    $this->assertCount(1, $revision_base_data['table']['join']);
+    $this->assertCount(2, $revision_base_data['table']['join']);
     $this->assertEquals([
       'entity_test_mulrev_property_revision' => [
         'left_field' => 'revision_id',
         'field' => 'revision_id',
         'type' => 'INNER',
       ],
+      'entity_test_mul_property_data' => [
+        'left_field' => 'revision_id',
+        'field' => 'revision_id',
+      ],
     ], $revision_base_data['table']['join']);
 
     $this->assertFalse(isset($data['data_table']));
+
+    $this->assertEquals('entity_test_mul_property_data', $revision_field_data['id']['relationship']['base']);
+    $this->assertEquals('id', $revision_field_data['id']['relationship']['base field']);
+    $this->assertEquals('entity_test_mul_property_data', $revision_field_data['revision_id']['relationship']['base']);
+    $this->assertEquals('revision_id', $revision_field_data['revision_id']['relationship']['base field']);
   }
 
   /**
@@ -341,15 +355,24 @@ public function testRevisionTableWithRevisionDataTable() {
     ], $revision_field_data['table']['join']);
 
     $revision_base_data = $data['entity_test_mulrev_revision'];
-    $this->assertCount(1, $revision_base_data['table']['join']);
+    $this->assertCount(2, $revision_base_data['table']['join']);
     $this->assertEquals([
       'entity_test_mulrev_property_revision' => [
         'left_field' => 'revision_id',
         'field' => 'revision_id',
         'type' => 'INNER',
       ],
+      'entity_test_mulrev_field_data' => [
+        'left_field' => 'revision_id',
+        'field' => 'revision_id',
+      ],
     ], $revision_base_data['table']['join']);
     $this->assertFalse(isset($data['data_table']));
+
+    $this->assertEquals('entity_test_mulrev_field_data', $revision_field_data['id']['relationship']['base']);
+    $this->assertEquals('id', $revision_field_data['id']['relationship']['base field']);
+    $this->assertEquals('entity_test_mulrev_field_data', $revision_field_data['revision_id']['relationship']['base']);
+    $this->assertEquals('revision_id', $revision_field_data['revision_id']['relationship']['base field']);
   }
 
   /**
@@ -583,6 +606,11 @@ public function testRevisionTableFields() {
     $this->assertNumericField($data['entity_test_mulrev_property_revision']['id']);
     $this->assertViewsDataField($data['entity_test_mulrev_property_revision']['id'], 'id');
 
+    $this->assertEquals('entity_test_mulrev_property_data', $data['entity_test_mulrev_property_revision']['id']['relationship']['base']);
+    $this->assertEquals('id', $data['entity_test_mulrev_property_revision']['id']['relationship']['base field']);
+    $this->assertEquals('entity_test_mulrev_property_data', $data['entity_test_mulrev_property_revision']['revision_id']['relationship']['base']);
+    $this->assertEquals('revision_id', $data['entity_test_mulrev_property_revision']['revision_id']['relationship']['base field']);
+
     $this->assertLanguageField($data['entity_test_mulrev_property_revision']['langcode']);
     $this->assertViewsDataField($data['entity_test_mulrev_property_revision']['langcode'], 'langcode');
     $this->assertEquals('Translation language', $data['entity_test_mulrev_property_revision']['langcode']['title']);
diff --git a/core/modules/views/views.post_update.php b/core/modules/views/views.post_update.php
index cd925a9b845c2b9e50bacffb6d0f3278ab8c6110..b5407369121788fb6b996667d0321e4a67a76bff 100644
--- a/core/modules/views/views.post_update.php
+++ b/core/modules/views/views.post_update.php
@@ -87,3 +87,10 @@ function views_post_update_sort_identifier(?array &$sandbox = NULL): void {
     return $view_config_updater->needsSortFieldIdentifierUpdate($view);
   });
 }
+
+/**
+ * Clear caches due to adding a relationship from revision table to base table.
+ */
+function views_post_update_provide_revision_table_relationship() {
+  // Empty post-update hook.
+}