This document addresses the three main challenges you mentioned:
GitLab supports nested groups/subdirectories (e.g., group/subgroup/repo), but GitHub doesn't support nested repositories. All repositories in GitHub are flat.
The service implements multiple naming strategies to convert nested GitLab paths to flat GitHub repository names:
Converts all slashes to hyphens:
group/subgroup/repo→group-subgroup-repocompany/backend/api-service→company-backend-api-service
Use Case: When you want to preserve the full path information in the repository name.
Uses first and last segment:
group/subgroup/repo→group-repocompany/backend/api-service→company-api-service
Use Case: When you want to keep the top-level group and repository name but remove intermediate levels.
Uses only the repository name:
group/subgroup/repo→repocompany/backend/api-service→api-service
Use Case: When repository names are unique and you don't need group information.
Allows you to specify exact mappings for each repository:
{
"migration": {
"naming_strategy": "custom",
"name_mappings": {
"group/subgroup/complex-name": "simple-name",
"company/backend/api-service": "api",
"legacy/old/project": "new-project-name"
}
}
}Use Case: When you need specific names for certain repositories or want to rename them during migration.
The NameMapper class in pkg/migration/naming.go handles all naming conversions with validation:
- Validates GitHub repository name rules (1-100 characters, valid characters only)
- Suggests fixes for invalid names
- Prevents conflicts with reserved names
The service automatically generates names based on your selected strategy. The process:
- Discovery: Lists all repositories in the GitLab group (including nested groups)
- Mapping: Applies the selected naming strategy to each repository path
- Validation: Checks if the generated name is valid for GitHub
- Suggestion: If invalid, suggests a corrected name
- Conflict Check: Verifies the name doesn't already exist in GitHub
You can override automatic naming by using custom mappings in the configuration:
{
"migration": {
"naming_strategy": "flatten",
"name_mappings": {
"group/subgroup/special-repo": "my-custom-name",
"another/group/repo": "another-custom-name"
}
}
}Custom mappings take precedence over the selected strategy.
The service validates all generated names against GitHub's rules:
- Length: 1-100 characters
- Characters: Alphanumeric, hyphens, underscores, and dots only
- Cannot start or end with
.,-, or_ - Cannot be reserved names (github, api, www, etc.)
If a name is invalid, the service automatically suggests a corrected version.
- Full Git History: All commits, branches, and tags are preserved
- Branches: All branches are migrated
- Tags: All tags are migrated
- Default Branch: The default branch is preserved
Implementation: Uses git clone --mirror to clone the entire repository with all refs, then pushes to GitHub using git push --mirror.
- All issues with titles, descriptions, and metadata
- Issue labels (migrated separately)
- Issue comments (preserved in issue body)
- Issue creation date and author information
Implementation: Fetches all issues from GitLab API and creates corresponding issues in GitHub with metadata preserved in the issue body.
- All merge requests converted to pull requests
- Source and target branches
- Descriptions and metadata
- Author information
Note: Merge requests are created as pull requests. The branches must exist first (handled during code migration).
- All labels with colors and descriptions
- Label names are preserved
- Colors are converted from GitLab format to GitHub format
Implementation: Fetches all labels and creates them in GitHub before migrating issues.
- All milestones with titles and descriptions
- Due dates (if set)
- Milestone states
Implementation: Fetches all milestones and creates them in GitHub before migrating issues.
- Wiki pages are detected and listed
- Full wiki migration requires manual steps (GitHub wikis are separate git repositories)
Current Implementation: Lists all wiki pages and logs them. Full wiki migration would require:
- Cloning the GitLab wiki repository
- Creating a GitHub wiki repository
- Pushing the wiki content
Future Enhancement: Full wiki migration can be implemented by cloning and pushing wiki repositories.
You can control what gets migrated:
{
"migration": {
"migrate_code": true,
"migrate_issues": true,
"migrate_merge_requests": true,
"migrate_wikis": true,
"migrate_labels": true,
"migrate_milestones": true,
"migrate_branches": true,
"migrate_tags": true,
"preserve_history": true,
"dry_run": false
}
}-
Discovery Phase
- Lists all repositories in the GitLab group
- Identifies nested repositories
- Maps GitLab paths to GitHub names
-
Validation Phase
- Validates repository names
- Checks for existing repositories in GitHub
- Suggests fixes for invalid names
-
Code Migration Phase
- Clones repository with full history
- Pushes to GitHub with all branches and tags
-
Metadata Migration Phase (in order)
- Migrates labels (required for issues)
- Migrates milestones (required for issues)
- Migrates issues (uses labels and milestones)
- Migrates merge requests (requires branches)
- Migrates wikis (if enabled)
-
Verification Phase
- Checks migration status
- Reports results and errors
The service provides comprehensive error handling:
- Per-Repository Errors: Each repository migration tracks its own errors
- Warnings: Non-critical issues (like name changes) are logged as warnings
- Detailed Logs: All operations are logged for troubleshooting
- Status Reporting: Migration status is available via API
Test migrations without actually creating repositories:
{
"migration": {
"dry_run": true
}
}Or via API:
POST /api/v1/migration/repositories/:path/migrate
{
"dry_run": true
}The service provides a complete solution for migrating from GitLab to GitHub:
- Nested Repository Handling: Multiple naming strategies to convert nested paths to flat names
- Flexible Naming: Automatic name generation with manual override capability
- Complete Migration: Code, issues, PRs, labels, milestones, and wikis (with limitations)
All solutions are configurable and can be customized to fit your specific migration needs.