Skip to content

katiem0/gh-bbc-exporter

Repository files navigation

gh-bbc-exporter

GitHub Release PR Checks License: MIT Go Report Card Go Version

A GitHub gh CLI extension for exporting Bitbucket Cloud repositories into a format compatible with GitHub Enterprise migrations.

Caution

Breaking changes have been introduced in version v3.0.0

  • The CLI now uses subcommands: export for exporting only, and migrate for export + import

Overview

This extension helps you migrate repositories from Bitbucket Cloud to GitHub Enterprise Cloud, GitHub Enterprise Cloud Managed Users, and GitHub Enterprise Cloud with data residency by creating an export archive that matches the format expected by GitHub Enterprise Importer (GEI).

The exporter creates a complete migration archive containing:

  • Repository metadata
  • Git objects (commits, branches, tags)
  • Pull requests with comments
  • Pull request reviews
  • User information

Installation

gh extension install katiem0/gh-bbc-exporter

For more information: gh extension install.

Prerequisites

  • GitHub CLI installed and authenticated
  • Bitbucket Cloud workspace administration access
  • Go 1.19 or higher (if building from source)

Bitbucket Authentication Options

Bitbucket Cloud provides two authentication methods for their API:

  • API Tokens (recommended)
  • Workspace Access Tokens (premium membership)
  • Basic Authentication with App Passwords (deprecated, will be discontinued after September 9, 2025)

Important

The extension uses the following authentication priority order:

  1. Workspace Access Token (--access-token / BITBUCKET_ACCESS_TOKEN)
  2. API Token with Email (--api-token + --email / BITBUCKET_API_TOKEN + BITBUCKET_EMAIL)
  3. API Token with header auth (--api-token / BITBUCKET_API_TOKEN)
  4. Username and App Password (--user + --app-password / BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD)

If multiple methods are provided, a warning is displayed and the highest priority method is used.

API Tokens

API tokens are the recommended authentication method and will replace app passwords. To create an API token:

  1. Log in to Bitbucket Cloud
  2. Click on your profile avatar in the top right
  3. Select Atlassian account settings
  4. In the top navigation section, select Security
  5. Click Create and manage API tokens
  6. Select Create API token with scopes
  7. Give your token a name and expiration date
  8. Select Bitbucket API token app and select the following permissions:
    • read:account
    • read:pullrequest:bitbucket
    • read:repository:bitbucket
    • read:workspace:bitbucket
  9. Click Next, review scopes and click Create
  10. Copy the token immediately as you won't be able to see it again

Basic Authentication with App Passwords

Warning

App passwords will be discontinued after September 9, 2025. Creation of new app passwords will stop after that date, and existing app passwords will stop working on June 9, 2026. Please migrate to API tokens instead.

For basic authentication with this tool your account username and an app password are needed. Your Bitbucket username can be found by following:

  1. On the sidebar, click on the Profile picture
  2. Select View profile
  3. Click on "Settings"
  4. Find Username under Bitbucket profile settings

To create an app password:

  1. Under Personal settings, select Personal Bitbucket settings.
  2. On the left sidebar, select App passwords.
  3. Select Create app password.
  4. Give the App password a name.
  5. Select the following permissions:
    • Account: Read
    • Workspace Membership: Read
    • Repositories: Read
    • Pull Requests: Read
  6. Select the Create button. The page will display the New app password dialog.

Workspace Access Token

A workspace-level access token is required to ensure a list of users is retrieved to be able to associate metadata with their GitHub account.

The access token will require the following permissions:

  • Account: Read
  • Repositories: Read
  • Pull Requests: Read

Usage

The gh-bbc-exporter extension supports the retrieval of repositories or migrating repositories with GitHub-Owned Storage from Bitbucket Cloud:

gh bbc-exporter -h
Export and migrate repositories from Bitbucket Cloud to GitHub

Usage:
  bbc-exporter [command]

Available Commands:
  export      Export repository and metadata from Bitbucket Cloud
  migrate     Export from Bitbucket and import to GitHub

Flags:
      --help   Show help for command

Use "bbc-exporter [command] --help" for more information about a command.

Export Command

The export command exports a repository from Bitbucket Cloud and creates a local migration archive:

gh bbc-exporter export -h
Export repository and metadata from Bitbucket Cloud for GitHub Cloud import.

Usage:
  bbc-exporter export [flags]

Flags:
  -a, --bbc-api-url string     Bitbucket API to use (default "https://api.bitbucket.org/2.0")
  -t, --access-token string    Bitbucket workspace access token for authentication (env: BITBUCKET_ACCESS_TOKEN)
      --api-token string       Bitbucket API token for authentication (env: BITBUCKET_API_TOKEN)
  -e, --email string           Atlassian account email for API token authentication (env: BITBUCKET_EMAIL)
  -u, --user string            Bitbucket username for basic authentication (env: BITBUCKET_USERNAME)
  -p, --app-password string    Bitbucket app password for basic authentication (env: BITBUCKET_APP_PASSWORD)
  -w, --workspace string       Bitbucket workspace name
  -r, --repo string            Name of the repository to export from Bitbucket Cloud
      --temp-dir string        Temporary directory for cloning (env: BITBUCKET_TEMP_DIR)
  -o, --output string          Output directory for exported data (default: ./bitbucket-export-TIMESTAMP)
      --open-prs-only          Export only open pull requests and ignore closed/merged ones
      --prs-from-date string   Export pull requests created on or after this date (format: YYYY-MM-DD)
      --skip-commit-lookup     Skip Bitbucket API lookups to retrieve commit SHAs (use local lookup only)
  -d, --debug                  Enable debug logging

Global Flags:
      --help   Show help for command

Export Examples

# Export using API token with email (recommended)
gh bbc-exporter export -w your-workspace -r your-repo --api-token your-api-token --email your-email@example.com

# Export using workspace access token
gh bbc-exporter export -w your-workspace -r your-repo -t your-workspace-token

# Export using basic authentication (deprecated)
gh bbc-exporter export -w your-workspace -r your-repo -u your-username -p your-app-password

# Export only open pull requests
gh bbc-exporter export -w your-workspace -r your-repo -t your-token --open-prs-only

# Export pull requests from a specific date
gh bbc-exporter export -w your-workspace -r your-repo -t your-token --prs-from-date 2024-01-01

Migrate Command

The migrate command combines export and import into a single operation, exporting from Bitbucket Cloud and importing directly to GitHub Enterprise Cloud using GitHub-Owned Storage:

gh bbc-exporter migrate -h
Migrate a repository from Bitbucket Cloud to GitHub Enterprise.

Usage:
  bbc-exporter migrate [flags]

Flags:
  -a, --bbc-api-url string                                 Bitbucket API to use (default "https://api.bitbucket.org/2.0")
  -t, --access-token string                                Bitbucket workspace access token for authentication (env:
                                                           BITBUCKET_ACCESS_TOKEN)
      --api-token string                                   Bitbucket API token for authentication (env: BITBUCKET_API_TOKEN)
  -e, --email string                                       Atlassian account email for API token authentication (env:
                                                           BITBUCKET_EMAIL)
  -u, --user string                                        Bitbucket username for basic authentication (env:
                                                           BITBUCKET_USERNAME)
  -p, --app-password string                                Bitbucket app password for basic authentication (env:
                                                           BITBUCKET_APP_PASSWORD)
  -w, --workspace string                                   Bitbucket workspace name
  -r, --repo string                                        Name of the repository to export from Bitbucket Cloud
      --temp-dir string                                    Temporary directory for cloning (env: BITBUCKET_TEMP_DIR)
  -o, --output string                                      Output directory for exported data (default:
                                                           ./bitbucket-export-TIMESTAMP)
      --open-prs-only                                      Export only open pull requests
      --prs-from-date string                               Export pull requests created on or after this date (format:
                                                           YYYY-MM-DD)
      --skip-commit-lookup                                 Skip Bitbucket API lookups to retrieve commit SHAs (use local
                                                           lookup only)
      --target-org string                                  Target GitHub organization (required)
      --target-repo string                                 Target repository name (defaults to source repo name)
      --github-target-pat string                           GitHub Personal Access Token (env: GITHUB_PAT)
      --target-api-url string                              The URL of the target API, if not migrating to github.com.
                                                           Defaults to https://v-api-github-com.adclosenn.dev (default
                                                           "https://api.github.com")
      --target-repo-visibility <internal|private|public>   The visibility of the target repo. Defaults to private. Valid
                                                           values are public, private, or internal. (default private)
  -d, --debug                                              Enable debug logging

Global Flags:
      --help   Show help for command

Migrate Examples

# Migrate repository to GitHub (uses gh CLI authentication by default)
gh bbc-exporter migrate -w bitbucket-workspace -r source-repo \
   --target-org github-org -t your-bitbucket-token

# Migrate with custom target repository name
gh bbc-exporter migrate -w bitbucket-workspace -r source-repo \
   --target-org github-org --target-repo new-repo-name -t your-token

# Migrate with specific visibility
gh bbc-exporter migrate -w bitbucket-workspace -r source-repo \
   --target-org github-org --target-repo-visibility internal \
   -t your-token

# Migrate and keep the archive for inspection
gh bbc-exporter migrate -w bitbucket-workspace -r source-repo \
   --target-org github-org -t your-token

# Migrate using explicit GitHub PAT
gh bbc-exporter migrate -w bitbucket-workspace -r source-repo \
   --target-org github-org --github-target-pat ghp_xxxxx \
   -t your-bitbucket-token

Migrating to GitHub Enterprise Cloud with Data Residency

For migrations to a GHE.com instance, use the --target-api-url flag:

gh bbc-exporter migrate -w bitbucket-workspace -r source-repo \
   --target-org github-org \
   --target-api-url https://api.your-slug.ghe.com \
   --github-target-pat ghp_xxxxx \
   -t your-bitbucket-token

Note

GitHub Enterprise Cloud with data residency (GHE.com) requires the --target-api-url flag pointing to your instance's API endpoint. The uploads URL is automatically derived from the API URL. GitHub Enterprise Server (GHES) is not supported.

Advanced Options

Skip Commit SHA Lookups

The --skip-commit-lookup flag can be used to improve export performance by skipping Bitbucket API calls for resolving full commit SHAs. When enabled:

  • The tool will only attempt to resolve commit SHAs from the locally cloned repository
  • If a full SHA cannot be resolved locally, the short SHA will be preserved
  • This can significantly reduce API calls and speed up exports for large repositories with many pull request comments

When to use this flag:

  • When experiencing rate limiting issues with the Bitbucket API
  • For large repositories with many pull request review comments
  • When you're confident the local repository clone contains all referenced commits

Note

Some GitHub import operations may require full 40-character commit SHAs. Only use this flag if you're certain that shortened SHAs won't cause issues with your migration, or if the local repository contains all the necessary commit history.

# Export with skip commit lookup enabled
gh bbc-exporter export -w your-workspace -r your-repo --skip-commit-lookup -t your-token

# Migrate with skip commit lookup enabled
gh bbc-exporter migrate -w your-workspace -r your-repo --target-org github-org --skip-commit-lookup -t your-token

Authentication Methods

Using Environment Variables

This tool supports the use of environment variables instead of command-line flags:

# API token authentication with email (recommended)
export BITBUCKET_API_TOKEN="your-api-token-here"
export BITBUCKET_EMAIL="your-atlassian-email@example.com"
gh bbc-exporter export -w your-workspace -r your-repo

# Workspace token authentication
export BITBUCKET_ACCESS_TOKEN="your-workspace-token-here"
gh bbc-exporter export -w your-workspace -r your-repo

# Basic authentication (soon to be deprecated)
export BITBUCKET_USERNAME="your-username"
export BITBUCKET_APP_PASSWORD="your-app-password"
gh bbc-exporter export -w your-workspace -r your-repo

# GitHub PAT for migrate command
export GITHUB_PAT="ghp_your-github-pat"
gh bbc-exporter migrate -w your-workspace -r your-repo --target-org github-org -t your-bitbucket-token

Command-line Authentication

# Using API token with email (recommended)
gh bbc-exporter export -w your-workspace -r your-repo --api-token your-api-token --email your-atlassian-email@example.com

# Using workspace access token
gh bbc-exporter export -w your-workspace -r your-repo -t your-workspace-token

# Using basic authentication (soon to be deprecated)
gh bbc-exporter export -w your-workspace -r your-repo -u your-username -p your-app-password

For migrations from BitBucket Data Center or Server, please see GitHub's Official Documentation.

Export Format

The exporter creates a directory or archive with the following structure:

bitbucket-export-YYYYMMDD-HHMMSS/
├── schema.json
├── repositories_000001.json
├── users_000001.json
├── organizations_000001.json
├── pull_requests_000001.json
├── issue_comments_000001.json
├── pull_request_review_comments_000001.json
├── pull_request_review_threads_000001.json
├── pull_request_reviews_000001.json
└── repositories/
    └── <workspace>/
        └── <repository>.git/
            ├── objects/
            ├── refs/
            └── info/
                ├── nwo
                └── last-sync

Importing to GitHub Enterprise Cloud

After generating the migration archive with the export command, you can import it to GitHub Enterprise Cloud using GitHub owned storage and GEI. Detailed documentation can be found in Importing Bitbucket Cloud Archive to GitHub Enterprise Cloud.

Alternatively, use the migrate command to perform both export and import in a single operation.

Automated Migration with GitHub Actions

A sample GitHub Actions workflow is available to automate the export and import process. See the sample workflow for an example of how to orchestrate the migration.

Limitations

  • API rate limits may affect large exports
  • Wiki content is not included in the export
  • Issues are not exported (Bitbucket issues have a different structure from GitHub issues)
  • Repository and Pull request labels have not been implemented
  • User information is limited to what's available from Bitbucket API
  • Archives larger than 40 GiB are not supported by GitHub-owned storage
  • GitHub Enterprise Server (GHES) is not supported as a migration target

Repository Name Handling

When exporting repositories with special characters in their names:

  • The tool will preserve capitalization in repository names (e.g., RepositoryUIName)
  • If a repository name contains special characters that aren't allowed in GitHub repository names (e.g., @group-test/ui), the tool will use the Bitbucket slug (e.g., group-test-ui) for compatibility
  • Repository slugs are always used for directory names and internal references to ensure consistency

Git Reference Validation

The exporter validates Git references (branch and tag names) to prevent ambiguous references that could cause issues during GitHub import. The following validations are performed:

  • Ambiguous references: Branch or tag names that are exactly 40 hexadecimal characters are rejected, as they could be mistaken for commit SHAs
  • Invalid characters: References containing special characters like spaces, ~, ^, :, ?, *, [, \, .., @{, or // are flagged
  • Invalid formats: References that start or end with ., /, or end with .lock are considered invalid

If any ambiguous references are detected, the export will fail with a clear error message indicating which references need to be renamed in Bitbucket before attempting the export again.

Troubleshooting

Common Issues

  1. Authentication Errors Make sure your Bitbucket app password has the necessary permissions to access repositories.
  2. Export Fails with Network Errors Bitbucket API may have rate limits. Try running the export with the --debug flag to see detailed error messages.
  3. Empty Repository Export If the repository can't be cloned, the exporter creates an empty repository structure. Check that the repository exists and is accessible.
  4. Migration Fails in GitHub Enterprise Importer Check the error logging repository that's created during migration for detailed information about any failures.
  5. Export Fails Due to Ambiguous Git References If your repository has branches or tags with names that are exactly 40 hexadecimal characters (e.g., 1234567890abcdef1234567890abcdef12345678), the export will fail. These references are ambiguous because Git cannot determine if they refer to a branch/tag name or a commit SHA. To resolve:
    • Rename the problematic branches/tags in Bitbucket to use non-ambiguous names
    • Re-run the export after renaming
  6. GitHub CLI Authentication Issues If using gh CLI authentication and you receive GraphQL: <user> does not have the correct permissions to execute, it is likely due to auth permissions from the CLI. See gh auth login for details on --scopes.

Development

Building from Source

  1. Clone the repository:

    git clone https://github.com/katiem0/gh-bbc-exporter.git
    cd gh-bbc-exporter
  2. Build the extension:

    go build -o gh-bbc-exporter
  3. Install locally for testing:

    gh extension install .

Running Tests

go test ./...

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

About

A GitHub CLI extension to create a Bitbucket Cloud archive for import to GitHub Enterprise Cloud.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Contributors

Languages