Skip to content

Git Destinations

Git destinations define where Copybara writes transformed code.

Direct push to a Git repository:

destination = git.destination(
url = "https://github.com/org/repo.git",
fetch = "main",
push = "main",
)
ParameterRequiredDescription
urlYesRepository URL (HTTPS or SSH)
pushYesBranch to push to
fetchNoBranch to fetch (default: same as push)
tag_nameNoCreate a tag with this name
tag_msgNoTag message
skip_pushNoSkip the push (for testing)
# Basic push to main
destination = git.destination(
url = "https://github.com/org/repo",
push = "main",
)
# Push to different branch
destination = git.destination(
url = "https://github.com/org/repo",
fetch = "main",
push = "sync/latest",
)
# Create a tag
destination = git.destination(
url = "https://github.com/org/repo",
push = "main",
tag_name = "v${VERSION}",
tag_msg = "Release ${VERSION}",
)
# SSH URL
destination = git.destination(
url = "git@github.com:org/repo.git",
push = "main",
)

GitHub-specific destination with API integration:

destination = git.github_destination(
url = "https://github.com/org/repo",
push = "main",
)
  • Automatic CODEOWNERS validation
  • GitHub API integration for metadata
  • Better error messages for GitHub-specific issues
destination = git.github_destination(
url = "https://github.com/org/repo",
push = "main",
skip_push = False,
)

Create pull requests instead of pushing directly:

destination = git.github_pr_destination(
url = "https://github.com/org/repo",
destination_ref = "main",
pr_branch = "copybara/sync-${CONTEXT_REFERENCE}",
)
ParameterRequiredDescription
urlYesRepository URL
destination_refYesTarget branch for the PR
pr_branchNoBranch name for the PR
titleNoPR title
bodyNoPR description
draftNoCreate as draft PR
update_descriptionNoUpdate PR description on re-run
assigneesNoList of assignees
labelsNoList of labels
# Basic PR
destination = git.github_pr_destination(
url = "https://github.com/org/repo",
destination_ref = "main",
)
# Full configuration
destination = git.github_pr_destination(
url = "https://github.com/org/repo",
destination_ref = "main",
pr_branch = "copybara/sync-${CONTEXT_REFERENCE}",
title = "Sync from internal",
body = """\
Automated sync from internal repository.
Please review and merge.
""",
draft = False,
update_description = True,
assignees = ["reviewer1"],
labels = ["automated", "sync"],
)

Create Gerrit change lists:

destination = git.gerrit_destination(
url = "https://gerrit.example.com/repo",
fetch = "main",
push_to_refs_for = "main",
)
ParameterDescription
urlGerrit repository URL
fetchBranch to fetch
push_to_refs_forTarget branch for the CL
submitAuto-submit after creating
notifyNotification setting
destination = git.gerrit_destination(
url = "https://gerrit.example.com/repo",
fetch = "main",
push_to_refs_for = "main",
notify = "OWNER", # Notify owner only
)

The fetch and push parameters serve different purposes:

  • fetch: The branch to read current state from (for merging)
  • push: The branch to push changes to
# Same branch (common)
destination = git.destination(
url = "...",
push = "main",
) # fetch defaults to push
# Different branches
destination = git.destination(
url = "...",
fetch = "main", # Read from main
push = "sync/main", # Push to sync/main
)

For testing without actually pushing:

destination = git.destination(
url = "...",
push = "main",
skip_push = True, # Don't actually push
)

Copybara handles push conflicts:

  1. Normal push: Fast-forward only
  2. With --force: Force push (destructive!)
Terminal window
# Normal (safe)
java -jar copybara.jar migrate copy.bara.sky
# Force (destructive)
java -jar copybara.jar migrate copy.bara.sky --force

Destinations require write access:

Terminal window
# HTTPS with token
git config --global credential.helper store
echo "https://x-access-token:${TOKEN}@github.com" > ~/.git-credentials
# SSH
ssh-add ~/.ssh/id_ed25519