Bitbucket → GitHub Migration Guide
Version: 2.0 Last Updated: 2025-10-18
Overview
This guide explains how to migrate a Bitbucket Cloud repository to GitHub, preserving:
- Git history (branches, tags, commits)
- Issues, pull requests, and comments
- Attachments (manual upload required)
- Author and timestamp metadata (as text)
Important Safety Note
Keep your Bitbucket repository intact (potentially archived) until migration is fully verified. If errors occur and migration is only partially completed, delete the GitHub repository and start fresh.
Installation and Setup
-
Install from PyPI (Recommended):
Then use as follows. See CLI Reference Guide for detailed description of the command line interface of the included scripts.pipx install bitbucket-migrationmigrate_bitbucket_to_github audit --workspace YOUR_WORKSPACE --repo YOUR_REPO migrate_bitbucket_to_github dry-run --config migration_config.jsonAlternative installation methods
Run Directly
pipx run bitbucket-migration migrate_bitbucket_to_github audit --workspace YOUR_WORKSPACE --repo YOUR_REPOFrom Source
git clone https://github.com/fkloosterman/bitbucket-migration.git cd bitbucket-migration python migrate_bitbucket_to_github.py audit --workspace YOUR_WORKSPACE --repo YOUR_REPO -
Set up Bitbucket and Github Tokens
You will need a Bitbucket Cloud API Token (read access to repos, issues, PRs) and a GitHub Personal Access Token (PAT) with
reposcope.See API Tokens Setup Guide for instructions on how to setup these tokens and to verify access.
Migration Steps
flowchart TD
A(
**1. Audit Bitbucket Repository**
Collect metadata and create config.
) --> B(
**2. Mirror Git Repository**
Copy commits, branches, and tags.
)
click A "#step-1-run-audit" "migrate_bitbucket_to_github audit"
click B "#step-2-prepare-github-repository" "Mirror Git Repo"
B --> C(
**3. Tailor Configuration**
GitHub token, member mapping, repository mapping.
)
click C "#step-3-tailor-configuration" "Tailor Config"
C --> D(
**4. Dry Run Migration**
Validate config and check migration of issues and PRs.
)
D --> C
click D "#step-4-dry-run-migration" "Dry Run Migration"
D --> E(
**5. Run Full Migration**
Migrate issues, PRs, and comments.
)
click E "#step-5-run-full-migration" "Run Full Migration"
E --> F(
**6. Upload Attachments**
Automated with --use-gh-cli or manual upload.
)
click F "#step-6-upload-attachments" "Upload Attachments"
F --> G(
**6. Verify & Clean Up**
Finalize and verify migration.
)
click G "#step-7-verify-and-clean-up" "Verify"
Step-by-Step Migration
Step 1 — Run Audit
Generates the initial configuration and user mapping.
migrate_bitbucket_to_github audit \
--workspace WORKSPACE \
--repo REPO \
--email YOU@DOMAIN \
--gh-owner GITHUB_USER \
--gh-repo REPO
Outputs
audit_report.md– summary of repo datamigration_config.json– template for migrationuser_mapping_template.txt– list of contributors
Next: Edit the config file to map Bitbucket users to GitHub accounts. See User Mapping Reference.
Step 2 — Mirror Repository
- Create an empty repository on GitHub. Do not add a README or license.
- Keep it private until migration is complete.
git clone --mirror https://bitbucket.org/WORKSPACE/REPO.git
cd REPO.git
git remote add github https://github.com/OWNER/REPO.git
git push --mirror github
Verify:
git ls-remote github
Step 3 - Tailor Configuration
Edit migration_config.json to set your tokens and user mappings. See Migration Config Reference for full details.
- Update Tokens
- Set
bitbucket.tokento your Bitbucket API token. -
Set
github.tokento your GitHub PAT withreposcope. -
Configure User Mapping
- Map Bitbucket display names to GitHub usernames in
user_mapping. -
Set unmapped or deleted users to
null. -
Run Dry Run
- After editing, run a dry run (Step 4) to validate.
- Refine mappings if needed.
Advanced Options
- Add
repository_mappingfor cross-repository link rewriting. - See Migration Config Reference for details.
Step 4 — Dry Run Migration
Run a simulation of the migration to validate your configuration without making any changes.
migrate_bitbucket_to_github dry-run \
--config migration_config.json
What it does:
- Validates tokens and permissions.
- Checks user mappings and repository access.
- Estimates issue/PR counts and migration time.
- Generates migration_report_dry_run.md with details.
Check for:
- Authentication success (no 401/403 errors).
- Valid user mappings (no unmapped users warnings).
- Correct counts matching your audit report.
- If issues, refine migration_config.json and retry.
Advanced Options
- Use
--skip-issuesor--skip-prsto test specific phases. - See CLI Reference for all options.
Step 5 — Run Full Migration
Execute the actual migration of issues, PRs, comments, and attachments.
migrate_bitbucket_to_github migrate \
--config migration_config.json
What it does:
- Migrates issues and PRs (open PRs stay as PRs; closed PRs become issues).
- Downloads attachments to attachments_temp/.
- Generates migration_mapping.json for ID cross-references.
- Creates migration_report.md with details and any issues.
Advanced Options
- Use
--use-gh-clifor automatic attachment upload. - Use
--skip-issuesor--skip-prsto migrate selectively. - See CLI Reference for all options.
Step 6 — Upload Attachments
Attachments are downloaded locally because GitHub’s API doesn’t support direct upload. Use the --use-gh-cli option in the migration script for automated upload, or follow the manual steps below.
Automated Upload (Recommended)
Add --use-gh-cli to the migration command for automatic attachment upload:
migrate_bitbucket_to_github migrate --config migration_config.json --use-gh-cli
This requires GitHub CLI installed and authenticated.
Manual Upload
-
Locate Files
cd attachments_temp/ ls -lh -
Identify Targets Check GitHub issues for comments like:
📎 **Attachment from Bitbucket**: `file.png` (size) -
Upload
- Drag and drop files into issue comments on GitHub.
- Files preview inline or as links.
-
Verify
- Confirm uploads in GitHub issues.
Advanced Options
For bulk uploads or prioritization:
Bulk Upload with GitHub CLI
gh auth login
cd attachments_temp
while IFS=',' read -r file issue_num; do
gh issue comment "$issue_num" --repo OWNER/REPO --body "**Attachment:** $file" --attach "$file"
sleep 2
done < attachment_mapping.csv
Prioritization | Priority | Files | Action | |----------|-------|--------| | Critical | Screenshots, docs | Upload first | | Optional | Old files | Skip if needed |
Tracking & Cleanup
- Create attachment-status.md for progress.
- Backup: tar -czf attachments_backup.tar.gz attachments_temp/
- Delete: rm -rf attachments_temp/ after verification.
Step 7 — Verify and Clean Up
Confirm migration success and finalize the process.
Essential Checks:
- Verify Git history: branches, tags, and commits match Bitbucket.
- Check issue/PR counts and content against audit report.
- Spot-check user mentions, comments, and timestamps.
- Confirm attachments are uploaded (if not using --use-gh-cli).
Clean-Up Operations:
- Update README with new GitHub links and branch protections.
- Set Bitbucket repo to read-only or archive it.
- Clean up temporary files:
rm -rf attachments_temp/. - Archive migration reports and mappings for reference.
Support Resources
Checklist Before Asking for Help
- Confirm both API tokens are active and scoped correctly
- Compare audit vs. migrated item counts
- Check
migration_mapping.jsonfor missing IDs - Search console logs for
ERRORor429 - Verify no network or disk errors occurred
If problems persist, open a support ticket with a description of the error and the script version.