diff --git a/lib/gitlab/import_export/group/import_export.yml b/lib/gitlab/import_export/group/import_export.yml
index e30414265bea985fe19226041ae30682226caf1d..c2a1a1f8575191f09e5244be77133f4cd4665975 100644
--- a/lib/gitlab/import_export/group/import_export.yml
+++ b/lib/gitlab/import_export/group/import_export.yml
@@ -56,7 +56,6 @@ excluded_attributes:
     - :runners_token
     - :runners_token_encrypted
     - :saml_discovery_token
-    - :visibility_level
     - :trial_ends_on
     - :shared_runners_minute_limit
     - :extra_shared_runners_minutes_limit
diff --git a/lib/gitlab/import_export/group/tree_restorer.rb b/lib/gitlab/import_export/group/tree_restorer.rb
index 19d707aaca5632cbb116fb31719aba53d780af06..0b92942eb8ad938569e2552af4b3c47ab9c811fe 100644
--- a/lib/gitlab/import_export/group/tree_restorer.rb
+++ b/lib/gitlab/import_export/group/tree_restorer.rb
@@ -65,6 +65,15 @@ def process_root(group_id)
           # with existing groups name and/or path.
           group_attributes.delete_attributes('name', 'path')
 
+          if @top_level_group.has_parent?
+            group_attributes.attributes['visibility_level'] = sub_group_visibility_level(
+              group_attributes.attributes['visibility_level'],
+              @top_level_group.parent
+            )
+          elsif Gitlab::VisibilityLevel.restricted_level?(group_attributes.attributes['visibility_level'])
+            group_attributes.delete_attribute('visibility_level')
+          end
+
           restore_group(@top_level_group, group_attributes)
         end
 
@@ -86,6 +95,7 @@ def create_group(group_attributes)
           parent_id = group_attributes.delete_attribute('parent_id')
           name = group_attributes.delete_attribute('name')
           path = group_attributes.delete_attribute('path')
+          visibility_level = group_attributes.delete_attribute('visibility_level')
 
           parent_group = @groups_mapping.fetch(parent_id) { raise(ArgumentError, 'Parent group not found') }
 
@@ -94,7 +104,7 @@ def create_group(group_attributes)
             name: name,
             path: path,
             parent_id: parent_group.id,
-            visibility_level: sub_group_visibility_level(group_attributes.attributes, parent_group)
+            visibility_level: sub_group_visibility_level(visibility_level, parent_group)
           ).execute
 
           group.validate!
@@ -124,16 +134,23 @@ def relation_reader
           end
         end
 
-        def sub_group_visibility_level(group_hash, parent_group)
-          original_visibility_level = group_hash['visibility_level'] || Gitlab::VisibilityLevel::PRIVATE
+        def sub_group_visibility_level(visibility_level, parent_group)
+          parent_visibility_level = parent_group.visibility_level
 
-          if parent_group && parent_group.visibility_level < original_visibility_level
-            Gitlab::VisibilityLevel.closest_allowed_level(parent_group.visibility_level)
+          original_visibility_level = visibility_level ||
+            closest_allowed_level(parent_visibility_level)
+
+          if parent_visibility_level < original_visibility_level
+            closest_allowed_level(parent_visibility_level)
           else
-            original_visibility_level
+            closest_allowed_level(original_visibility_level)
           end
         end
 
+        def closest_allowed_level(visibility_level)
+          Gitlab::VisibilityLevel.closest_allowed_level(visibility_level)
+        end
+
         def reader
           strong_memoize(:reader) do
             Gitlab::ImportExport::Reader.new(
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1689.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1689.json
new file mode 100644
index 0000000000000000000000000000000000000000..4c0a29599b91e0c7bfd7f7d3d7be0d659699f950
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1689.json
@@ -0,0 +1,48 @@
+{
+  "depth": 1,
+  "tree_path": [
+    1689
+  ],
+  "tree_cycle": false,
+  "id": 1689,
+  "name": "public-group-3",
+  "path": "public-group-3",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 20,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": null,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1690.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1690.json
new file mode 100644
index 0000000000000000000000000000000000000000..f01c79b06d8e080e8572b6efe2b5f6f30b1b823e
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1690.json
@@ -0,0 +1,50 @@
+{
+  "depth": 2,
+  "tree_path": [
+    1689,
+    1690
+  ],
+  "tree_cycle": false,
+  "id": 1690,
+  "name": "private-subgroup",
+  "path": "private-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 0,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1689,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1690
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1691.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1691.json
new file mode 100644
index 0000000000000000000000000000000000000000..f9c08b420c0df99b79cedbe432a835de8e7dfaf1
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1691.json
@@ -0,0 +1,50 @@
+{
+  "depth": 2,
+  "tree_path": [
+    1689,
+    1691
+  ],
+  "tree_cycle": false,
+  "id": 1691,
+  "name": "internal-subgroup",
+  "path": "internal-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 10,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1689,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1691
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1692.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1692.json
new file mode 100644
index 0000000000000000000000000000000000000000..381230e86a8cbddad3895ca6759e2c92790cf999
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/1692.json
@@ -0,0 +1,50 @@
+{
+  "depth": 2,
+  "tree_path": [
+    1689,
+    1692
+  ],
+  "tree_cycle": false,
+  "id": 1692,
+  "name": "public-subgroup",
+  "path": "public-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 20,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1689,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1692
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2106.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2106.json
new file mode 100644
index 0000000000000000000000000000000000000000..1707e341129f6ec95605c165e16581c2a26fefc2
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2106.json
@@ -0,0 +1,52 @@
+{
+  "depth": 3,
+  "tree_path": [
+    1689,
+    1691,
+    2106
+  ],
+  "tree_cycle": false,
+  "id": 2106,
+  "name": "internal-sub-subgroup",
+  "path": "internal-sub-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 10,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1691,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1691,
+    2106
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2107.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2107.json
new file mode 100644
index 0000000000000000000000000000000000000000..cac1c82682134fec2ddceb97cfcdad298643993a
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2107.json
@@ -0,0 +1,52 @@
+{
+  "depth": 3,
+  "tree_path": [
+    1689,
+    1692,
+    2107
+  ],
+  "tree_cycle": false,
+  "id": 2107,
+  "name": "internal-sub-subgroup",
+  "path": "internal-sub-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 10,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1692,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1692,
+    2107
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2108.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2108.json
new file mode 100644
index 0000000000000000000000000000000000000000..d464b41e9086ab60a2d5fdab794515be17e0353b
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2108.json
@@ -0,0 +1,52 @@
+{
+  "depth": 3,
+  "tree_path": [
+    1689,
+    1692,
+    2108
+  ],
+  "tree_cycle": false,
+  "id": 2108,
+  "name": "public-sub-subgroup",
+  "path": "public-sub-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 20,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1692,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1692,
+    2108
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2109.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2109.json
new file mode 100644
index 0000000000000000000000000000000000000000..7f3adf364d75187e867ef99b313be380e692f147
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2109.json
@@ -0,0 +1,52 @@
+{
+  "depth": 3,
+  "tree_path": [
+    1689,
+    1692,
+    2109
+  ],
+  "tree_cycle": false,
+  "id": 2109,
+  "name": "private-sub-subgroup",
+  "path": "private-sub-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 0,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1692,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1692,
+    2109
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2110.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2110.json
new file mode 100644
index 0000000000000000000000000000000000000000..744b8d36b16e4fb9c7c317d3e2e8c0e178cfe9e0
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/2110.json
@@ -0,0 +1,52 @@
+{
+  "depth": 3,
+  "tree_path": [
+    1689,
+    1690,
+    2110
+  ],
+  "tree_cycle": false,
+  "id": 2110,
+  "name": "private-sub-subgroup",
+  "path": "private-sub-subgroup",
+  "description": "",
+  "avatar": {
+    "url": null
+  },
+  "membership_lock": false,
+  "share_with_group_lock": false,
+  "visibility_level": 0,
+  "request_access_enabled": true,
+  "ldap_sync_status": "ready",
+  "ldap_sync_error": null,
+  "ldap_sync_last_update_at": null,
+  "ldap_sync_last_successful_update_at": null,
+  "ldap_sync_last_sync_at": null,
+  "lfs_enabled": null,
+  "parent_id": 1690,
+  "shared_runners_minutes_limit": null,
+  "require_two_factor_authentication": false,
+  "two_factor_grace_period": 48,
+  "project_creation_level": 2,
+  "file_template_project_id": null,
+  "custom_project_templates_group_id": null,
+  "auto_devops_enabled": null,
+  "last_ci_minutes_notification_at": null,
+  "last_ci_minutes_usage_notification_level": null,
+  "subgroup_creation_level": 1,
+  "emails_disabled": null,
+  "max_artifacts_size": null,
+  "mentions_disabled": null,
+  "default_branch_protection": 2,
+  "unlock_membership_to_ldap": null,
+  "max_personal_access_token_lifetime": null,
+  "push_rule_id": null,
+  "shared_runners_enabled": true,
+  "allow_descendants_override_disabled_shared_runners": false,
+  "traversal_ids": [
+    1689,
+    1690,
+    2110
+  ],
+  "organization_id": 1
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/_all.ndjson b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/_all.ndjson
new file mode 100644
index 0000000000000000000000000000000000000000..6c0425eabf474d6f5928234675315a46e1673bbd
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/nested_subgroups/tree/groups/_all.ndjson
@@ -0,0 +1,9 @@
+1689
+1690
+1691
+1692
+2110
+2106
+2107
+2108
+2109
diff --git a/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
index a6afd0a36ec4ae16c7ab30353da9f245f2da25f3..9766d5d6d594c4b19f445c193b8c87635be58290 100644
--- a/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
@@ -177,30 +177,146 @@
     end
 
     context 'group visibility levels' do
-      let(:user) { create(:user) }
-      let(:shared) { Gitlab::ImportExport::Shared.new(group) }
-      let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
+      context 'when the @top_level_group is the destination_group' do
+        let(:user) { create(:user) }
+        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
+        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
+
+        shared_examples 'with visibility level' do |visibility_level, expected_visibilities|
+          context "when visibility level is #{visibility_level}" do
+            let(:group) { create(:group, visibility_level) }
+            let(:filepath) { "group_exports/visibility_levels/#{visibility_level}" }
+
+            before do
+              setup_import_export_config(filepath)
+              group_tree_restorer.restore
+            end
 
-      before do
-        setup_import_export_config(filepath)
+            it "imports all subgroups as #{visibility_level}" do
+              expect(group.children.map(&:visibility_level)).to match_array(expected_visibilities)
+            end
+          end
+        end
 
-        group_tree_restorer.restore
+        include_examples 'with visibility level', :public, [20, 10, 0]
+        include_examples 'with visibility level', :private, [0, 0, 0]
+        include_examples 'with visibility level', :internal, [10, 10, 0]
       end
 
-      shared_examples 'with visibility level' do |visibility_level, expected_visibilities|
-        context "when visibility level is #{visibility_level}" do
-          let(:group) { create(:group, visibility_level) }
-          let(:filepath) { "group_exports/visibility_levels/#{visibility_level}" }
+      context 'when the destination_group is the @top_level_group.parent' do
+        let(:user) { create(:user) }
+        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
+        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
+
+        shared_examples 'with visibility level' do |visibility_level, expected_visibilities, group_visibility|
+          context "when source level is #{visibility_level}" do
+            let(:parent) { create(:group, visibility_level) }
+            let(:group) { create(:group, visibility_level, parent: parent) }
+            let(:filepath) { "group_exports/visibility_levels/#{visibility_level}" }
+
+            before do
+              setup_import_export_config(filepath)
+              parent.add_maintainer(user)
+              group_tree_restorer.restore
+            end
 
-          it "imports all subgroups as #{visibility_level}" do
-            expect(group.children.map(&:visibility_level)).to match_array(expected_visibilities)
+            it "imports all subgroups as #{visibility_level}" do
+              expect(group.visibility_level).to eq(group_visibility)
+              expect(group.children.map(&:visibility_level)).to match_array(expected_visibilities)
+            end
           end
         end
+
+        include_examples 'with visibility level', :public, [20, 10, 0], 20
+        include_examples 'with visibility level', :private, [0, 0, 0], 0
+        include_examples 'with visibility level', :internal, [10, 10, 0], 10
+      end
+
+      context 'when the visibility level is restricted' do
+        let(:user) { create(:user) }
+        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
+        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
+        let(:group) { create(:group, :internal) }
+        let(:filepath) { "group_exports/visibility_levels/internal" }
+
+        before do
+          setup_import_export_config(filepath)
+          Gitlab::CurrentSettings.restricted_visibility_levels = [10]
+          group_tree_restorer.restore
+        end
+
+        after do
+          Gitlab::CurrentSettings.restricted_visibility_levels = []
+        end
+
+        it 'updates the visibility_level' do
+          expect(group.children.map(&:visibility_level)).to match_array([0, 0, 0])
+        end
       end
+    end
+
+    context 'when there are nested subgroups' do
+      let(:filepath) { "group_exports/visibility_levels/nested_subgroups" }
 
-      include_examples 'with visibility level', :public, [20, 10, 0]
-      include_examples 'with visibility level', :private, [0, 0, 0]
-      include_examples 'with visibility level', :internal, [10, 10, 0]
+      context "when destination level is :public" do
+        let(:user) { create(:user) }
+        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
+        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
+        let(:parent) { create(:group, :public) }
+        let(:group) { create(:group, :public, parent: parent) }
+
+        before do
+          setup_import_export_config(filepath)
+          parent.add_maintainer(user)
+          group_tree_restorer.restore
+        end
+
+        it "imports all subgroups with original visibility_level" do
+          expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+          expect(group.descendants.map(&:visibility_level))
+            .to match_array([0, 0, 0, 10, 10, 10, 20, 20])
+        end
+      end
+
+      context "when destination level is :internal" do
+        let(:user) { create(:user) }
+        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
+        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
+        let(:parent) { create(:group, :internal) }
+        let(:group) { create(:group, :internal, parent: parent) }
+
+        before do
+          setup_import_export_config(filepath)
+          parent.add_maintainer(user)
+          group_tree_restorer.restore
+        end
+
+        it "imports non-public subgroups with original level and public subgroups as internal" do
+          expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
+          expect(group.descendants.map(&:visibility_level))
+            .to match_array([0, 0, 0, 10, 10, 10, 10, 10])
+        end
+      end
+
+      context "when destination level is :private" do
+        let(:user) { create(:user) }
+        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
+        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
+        let(:parent) { create(:group, :private) }
+        let(:group) { create(:group, :private, parent: parent) }
+
+        before do
+          setup_import_export_config(filepath)
+          parent.add_maintainer(user)
+          group_tree_restorer.restore
+        end
+
+        it "imports all subgroups as private" do
+          expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+          expect(group.descendants.map(&:visibility_level))
+            .to match_array([0, 0, 0, 0, 0, 0, 0, 0])
+        end
+      end
     end
   end
 
diff --git a/spec/requests/import/gitlab_groups_controller_spec.rb b/spec/requests/import/gitlab_groups_controller_spec.rb
index 1766c48cca1d9603bdba6a1cd8334bf36c2d25a6..734a4cefc5cfa2c2360d5cd30b468313805e0497 100644
--- a/spec/requests/import/gitlab_groups_controller_spec.rb
+++ b/spec/requests/import/gitlab_groups_controller_spec.rb
@@ -69,7 +69,7 @@ def upload_archive(file, headers = {}, params = {})
 
         expect(GroupImportWorker).to have_received(:perform_async).with(user.id, group.id)
         expect(group.description).to eq 'A voluptate non sequi temporibus quam at.'
-        expect(group.visibility_level).to eq Gitlab::VisibilityLevel::PRIVATE
+        expect(group.visibility_level).to eq Gitlab::VisibilityLevel::PUBLIC
       end
     end