Skip to content

Quick Start

This guide walks you through creating your first Copybara workflow to sync code between repositories.

You have an internal repository with code you want to publish to GitHub:

internal-repo/
├── src/
│ ├── lib/
│ └── internal/ # Should NOT be published
├── docs/
└── tests/

Goal: Sync src/lib/ and docs/ to a public GitHub repository, excluding internal code.

Create a file named copy.bara.sky in your repository:

copy.bara.sky
# Define the sync workflow
core.workflow(
name = "export",
# Source repository
origin = git.origin(
url = "https://github.com/myorg/internal-repo",
ref = "main",
),
# Destination repository
destination = git.github_destination(
url = "https://github.com/myorg/public-repo",
push = "main",
),
# What to sync (exclude internal code)
origin_files = glob(
include = ["src/lib/**", "docs/**"],
exclude = ["**/internal/**"],
),
# How to handle authorship
authoring = authoring.pass_thru(
default = "Bot <bot@example.com>",
),
# Transformations to apply
transformations = [
# Move src/lib to root
core.move("src/lib/", "src/"),
],
# Combine all changes into one commit
mode = "SQUASH",
)

Before running, validate the configuration:

Terminal window
java -jar copybara_deploy.jar validate copy.bara.sky export

For the first sync, use --init-history to process all existing commits:

Terminal window
java -jar copybara_deploy.jar migrate copy.bara.sky export --init-history

This will:

  1. Read all commits from the origin
  2. Apply transformations
  3. Create commits in the destination
  4. Store state for future incremental syncs

After the initial sync, Copybara tracks state automatically. Just run:

Terminal window
java -jar copybara_deploy.jar migrate copy.bara.sky export

Copybara will only process new commits since the last sync.

If you don’t have direct push access, use github_pr_destination to create PRs:

copy.bara.sky
core.workflow(
name = "export-pr",
origin = git.origin(
url = "https://github.com/myorg/internal-repo",
ref = "main",
),
# Creates PRs instead of pushing directly
destination = git.github_pr_destination(
url = "https://github.com/myorg/public-repo",
destination_ref = "main",
pr_branch = "copybara/sync-${CONTEXT_REFERENCE}",
title = "Sync from internal",
),
origin_files = glob(["src/**"]),
authoring = authoring.pass_thru("Bot <bot@example.com>"),
mode = "SQUASH",
)
transformations = [
# Remove internal comments
core.replace(
before = "// INTERNAL: ${content}\n",
after = "",
regex_groups = {"content": ".*"},
),
]
transformations = [
core.replace(
before = "internal.corp.com",
after = "api.example.com",
),
]
transformations = [
core.verify_match(
regex = "INTERNAL_SECRET|API_KEY_\\w+",
verify_no_match = True,
),
]

This is normal if there are no new commits since the last sync. Use --force to re-sync anyway:

Terminal window
java -jar copybara_deploy.jar migrate copy.bara.sky export --force

Ensure Git credentials are configured:

Terminal window
# For HTTPS
git config --global credential.helper store
# For SSH
ssh-add ~/.ssh/id_ed25519

Copybara stores state in commit messages (look for GitOrigin-RevId). To reset:

Terminal window
java -jar copybara_deploy.jar migrate copy.bara.sky export --last-rev <sha>