Bitbucket
Atlassian’s Git hosting (Cloud and Server/Data Center)
Copybara provides first-class support for GitHub, GitLab, and Gerrit. For other platforms like Bitbucket, Azure DevOps, Gitea, or Codeberg, you can still use Copybara effectively with the right approach.
| Platform | Origin | Destination | PR/MR/CL Support |
|---|---|---|---|
| Generic Git | git.origin() | git.destination() | No |
| GitHub | git.github_origin() | git.github_destination() | git.github_pr_destination() |
| GitLab | git.gitlab_origin() | — | git.gitlab_mr_destination() (experimental) |
| Gerrit | git.gerrit_origin() | git.gerrit_destination() | Built-in (CLs) |
These popular platforms require workarounds for PR/MR creation:
Bitbucket
Atlassian’s Git hosting (Cloud and Server/Data Center)
Azure DevOps
Microsoft’s DevOps platform with Azure Repos
Gitea / Forgejo
Self-hosted, lightweight Git forges
Codeberg
Hosted Forgejo instance for open source
The right approach depends on your requirements:
| If You Need… | Use This Approach |
|---|---|
| Simplest possible setup | Direct Push |
| Code review without automation | Feature Branch + Manual PR |
| Scriptable PR creation | Platform CLI |
| Full Copybara integration | HTTP Endpoint |
| Existing CI infrastructure | Webhook + CI |
| Simple wrapper script | Post-Migration Script |
Works for: All platforms Limitations: No PR/MR creation, bypasses code review
The simplest approach uses generic Git endpoints:
core.workflow( name = "sync", origin = git.origin( url = "https://bitbucket.org/org/source-repo.git", ref = "main", ), destination = git.destination( url = "https://bitbucket.org/org/dest-repo.git", push = "main", ), authoring = authoring.overwrite("Sync Bot <sync@example.com>"),)Pros:
Cons:
Best for:
Works for: All platforms Effort: Low (manual step required)
Push to a feature branch, then create the PR manually in the platform’s UI:
destination = git.destination( url = "https://bitbucket.org/org/repo.git", push = "copybara/sync-latest", # Feature branch, not main)After Copybara runs, open the platform’s web UI and create a PR from copybara/sync-latest to main.
Pros:
Cons:
Best for:
Works for: Platforms with CLIs Effort: Medium
Run Copybara to push the branch, then use the platform’s CLI to create the PR:
#!/bin/bash# Step 1: Copybara pushes to feature branchjava -jar copybara.jar migrate copy.bara.sky sync
# Step 2: Create PR via platform CLI# Install: pip install atlassian-python-api# Or use the official CLIbb pr create \ --source copybara/sync \ --destination main \ --title "Sync from source repository"# Install: az extension add --name azure-devopsaz repos pr create \ --source-branch copybara/sync \ --target-branch main \ --title "Sync from source repository"# Install: go install code.gitea.io/tea@latesttea pr create \ --head copybara/sync \ --base main \ --title "Sync from source repository"Pros:
Cons:
See Bitbucket, Azure DevOps, or Gitea for complete examples.
Works for: Any platform with REST API Effort: High (requires Starlark coding)
Use Copybara’s http.endpoint() to create PRs via the platform’s API:
def _create_pr(ctx): response = ctx.destination.post( url = "https://api.bitbucket.org/2.0/repositories/org/repo/pullrequests", headers = {"Content-Type": "application/json"}, body = http.json({ "title": "Sync from source", "source": {"branch": {"name": "copybara/sync"}}, "destination": {"branch": {"name": "main"}}, }), ) return ctx.success() if response.status_code == 201 else ctx.error("PR creation failed")
core.feedback( name = "create_pr", origin = git.github_trigger( url = "https://github.com/org/repo", events = ["push"], ), destination = http.endpoint( hosts = [ http.host( host = "api.bitbucket.org", auth = http.bearer_auth( creds = credentials.static_secret("bb_token", "BITBUCKET_TOKEN"), ), ), ], ), actions = [core.action(impl = _create_pr)],)Pros:
Cons:
See platform-specific guides for complete http.endpoint() examples.
Works for: Any platform with webhooks Effort: Medium-High
Let your CI system handle PR creation when Copybara pushes:
[Copybara] --push--> [Branch] --webhook--> [CI System] --API--> [Create PR]Even if your destination is not GitHub, you can use GitHub Actions to create PRs elsewhere:
name: Create PR on Bitbucket
on: push: branches: ["copybara/**"]
jobs: create-pr: runs-on: ubuntu-latest steps: - name: Create Bitbucket PR run: | curl -X POST \ -H "Authorization: Bearer ${{ secrets.BITBUCKET_TOKEN }}" \ -H "Content-Type: application/json" \ -d '{ "title": "Sync from source", "source": {"branch": {"name": "${{ github.ref_name }}"}}, "destination": {"branch": {"name": "main"}} }' \ https://api.bitbucket.org/2.0/repositories/org/repo/pullrequestsPros:
Cons:
Works for: All platforms Effort: Low-Medium
A simple shell script that runs Copybara then creates the PR:
#!/bin/bashset -e
PLATFORM="${PLATFORM:-bitbucket}"SOURCE_BRANCH="copybara/sync"TARGET_BRANCH="main"
# Run Copybarajava -jar copybara.jar migrate copy.bara.sky sync
# Check if changes were pushedif git ls-remote --exit-code origin "$SOURCE_BRANCH" >/dev/null 2>&1; then echo "Changes pushed to $SOURCE_BRANCH, creating PR..."
case "$PLATFORM" in bitbucket) curl -X POST \ -H "Authorization: Bearer $BITBUCKET_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"title\":\"Sync\",\"source\":{\"branch\":{\"name\":\"$SOURCE_BRANCH\"}},\"destination\":{\"branch\":{\"name\":\"$TARGET_BRANCH\"}}}" \ "https://api.bitbucket.org/2.0/repositories/$WORKSPACE/$REPO/pullrequests" ;; azure) az repos pr create \ --source-branch "$SOURCE_BRANCH" \ --target-branch "$TARGET_BRANCH" \ --title "Sync from source" ;; gitea) curl -X POST \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"title\":\"Sync\",\"head\":\"$SOURCE_BRANCH\",\"base\":\"$TARGET_BRANCH\"}" \ "$GITEA_URL/api/v1/repos/$OWNER/$REPO/pulls" ;; esacelse echo "No changes to sync"fiPros:
Cons:
| Approach | Automation | Complexity | PR Creation | Best For |
|---|---|---|---|---|
| Direct Push | Full | Low | None | Mirrors, unprotected sync |
| Feature Branch + Manual | Partial | Low | Manual | Low-frequency, human review |
| Platform CLI | Full | Medium | Automated | Teams familiar with CLIs |
| HTTP Endpoint | Full | High | Automated | Full Copybara integration |
| Webhook + CI | Full | Medium | Automated | Existing CI infrastructure |
| Wrapper Script | Full | Low-Medium | Automated | Simple, portable automation |