Docs: Review transfer documentation

Problem

The transfer documentation is fragmented and difficult to understand. As part of &17968 (closed), we should review the current behaviour and ensure that we document how permissions behave exactly for different scenarios, such as:

  • Transferring a personal project to a group
  • Transferring a group project to a personal namespace
  • Transferring a group to another group
  • Transferring a group to become a top-level group

Proposal

Restructured group and project documentation

GitLab Transfer Documentation

Group Transfers

Overview

Group transfers move groups from one location to another within the same GitLab instance. You can restructure your organization hierarchy by:

  • Converting top-level groups to subgroups - Move a top-level group under another group
  • Converting subgroups to top-level groups - Move a subgroup out of its parent to become independent
  • Moving subgroups between parents - Transfer a subgroup to a different parent group

What Gets Transferred

Included:

  • All subgroups and projects within the group
  • Explicit group memberships and roles
  • Group settings and configurations

Not Included:

  • Inherited memberships (members lose access unless they have explicit membership in target location)

Prerequisites

  • Owner role required for both source and target groups
  • Target group must allow subgroup creation (if applicable)

Important Limitations & Considerations

Membership Changes

  • Inherited membership is lost - Only explicit group members are transferred
  • Ownership requirement - If current owners only have inherited membership, the person performing the transfer becomes the new owner

Visibility & Access

  • Visibility inheritance - If target parent has lower visibility, all subgroups and projects will be downgraded to match
  • Repository URLs change - Local repositories must be updated to point to new paths

Package & Registry Restrictions

  • npm packages - Transfers fail if top-level group contains npm packages following naming conventions
  • Container registry - Images in archived projects must be deleted before transfer
  • Package endpoints - Group-level packages (Maven, NuGet, PyPI, Composer, Debian) need endpoint updates
  • Instance-level packages - Package names need updates if moved to different top-level group

Subscription Restrictions

  • GitLab.com limitation - Top-level groups with active subscriptions cannot be transferred (subscription must be removed first)

Transfer Steps

  1. Navigate to your group: Search or go to → select your group
  2. Go to group settings: SettingsGeneral
  3. Access transfer options: Expand Advanced section
  4. Initiate transfer: Select Transfer group
  5. Choose destination: Select target group from dropdown
  6. Confirm transfer: Select Transfer group

Post-Transfer Actions

  • Update local repository remotes to new URLs
  • Verify group member access and permissions
  • Update package configurations if applicable
  • Test CI/CD pipelines and integrations

Project Transfers

Overview

Project transfers move individual projects between any namespaces within the same GitLab instance. This allows you to reorganize projects without losing data or configuration.

You can transfer projects in any of these scenarios:

  • Personal namespace to group - Move your personal project into a team or organization group
  • Group to group - Transfer projects between different groups for reorganization
  • Group to personal namespace - Move a group project to your personal namespace

What Gets Transferred

Project Components:

  • Issues, merge requests, and discussions
  • CI/CD pipelines and configurations
  • Project dashboards and wiki
  • Repository code and history

Membership:

  • Direct project members and their roles
  • Pending membership invitations

Automatic Adjustments:

  • New project-level labels created if matching group labels don't exist
  • Epic copies created in target group if needed (with separate copies per project)

Prerequisites

  • Owner role for the project being transferred
  • Maintainer role (minimum) for the target group
  • Target group must allow new project creation

Important Limitations & Considerations

Membership Changes

  • Inherited membership is lost - Members with only inherited access lose permissions
  • New permissions inherited - Project inherits member permissions from target group

Container Registry Restrictions

  • GitLab.com - Can only transfer within same top-level namespace
  • Self-managed - Project must not contain container images

Package Considerations

  • npm packages - Must remove packages following naming convention if root namespace changes
  • Post-transfer options - Update package scope OR republish without convention (loses instance endpoint access)

Other Restrictions

  • Security policies - Projects with security policies have them automatically unassigned
  • Path changes - Repository URLs change, requiring local repository updates

Transfer Steps

  1. Navigate to your project: Search or go to → select your project
  2. Go to project settings: SettingsGeneral
  3. Access transfer options: Expand Advanced section
  4. Choose destination: Under Transfer project, select target namespace
  5. Initiate transfer: Select Transfer project
  6. Confirm transfer: Enter project name and select Confirm

Subscription Tier Changes

When transferring from Premium/Ultimate to Free tier:

  • Access tokens revoked - All project access tokens are automatically revoked
  • Features removed - Pipeline subscriptions and test cases are deleted

Post-Transfer Actions

  • Update local repository remotes to new URLs
  • Verify project member access and permissions
  • Update package configurations and republish if needed
  • Test CI/CD pipelines and integrations
  • Review and reassign security policies if needed

Troubleshooting

Console Transfer Method

If UI transfer fails, use Rails console:

# Find the project
p = Project.find_by_full_path('<project_path>')

# Set current user (project owner)
current_user = p.creator

# Find target namespace
namespace = Namespace.find_by_full_path("<new_namespace>")

# Execute transfer
Projects::TransferService.new(p, current_user).execute(namespace)

References

Edited by Christina Lohr