Skip to content

Fork synchronization

Fork-based contribution is common in open-source workflows: you fork an upstream repo, work on a feature branch in your fork, and open a PR back to upstream. Forks drift quickly, so you need a routine sync. This recipe combines bb repo view to discover the upstream URL and plain git for the fetch/rebase/push.

  • Your local clone is the fork, not the upstream.
  • origin points at your fork.
  • The upstream is reachable as a separate remote (we’ll add it if missing).
  • You have permission to push to your fork’s main (or whichever branch you want to keep in sync).
#!/bin/bash
# sync-fork.sh - Keep a fork's main branch in sync with its upstream.
set -euo pipefail
UPSTREAM_WORKSPACE="${UPSTREAM_WORKSPACE:?set UPSTREAM_WORKSPACE}"
UPSTREAM_REPO="${UPSTREAM_REPO:?set UPSTREAM_REPO}"
BRANCH="${BRANCH:-main}"
# 1. Look up the upstream clone URL via bb (HTTPS).
upstream_url=$(bb repo view \
-w "$UPSTREAM_WORKSPACE" -r "$UPSTREAM_REPO" --json \
--jq '.links.clone[] | select(.name == "https") | .href')
if [ -z "$upstream_url" ]; then
echo "Could not resolve HTTPS clone URL for $UPSTREAM_WORKSPACE/$UPSTREAM_REPO" >&2
exit 1
fi
# 2. Add the upstream remote if it isn't there.
if ! git remote get-url upstream >/dev/null 2>&1; then
echo "Adding upstream remote: $upstream_url"
git remote add upstream "$upstream_url"
else
git remote set-url upstream "$upstream_url"
fi
# 3. Fetch upstream and your fork.
git fetch upstream "$BRANCH"
git fetch origin "$BRANCH"
# 4. Switch to the branch and rebase onto upstream.
git checkout "$BRANCH"
git rebase "upstream/$BRANCH"
# 5. Push the rebased branch back to your fork.
# Use --force-with-lease, NOT --force, so concurrent fork-side pushes aren't clobbered.
git push --force-with-lease origin "$BRANCH"
echo "Fork '$BRANCH' synced with upstream $UPSTREAM_WORKSPACE/$UPSTREAM_REPO"
Terminal window
UPSTREAM_WORKSPACE=acme \
UPSTREAM_REPO=widget \
BRANCH=main \
./sync-fork.sh

Recipe: sync, then open a PR for a feature branch

Section titled “Recipe: sync, then open a PR for a feature branch”

A common follow-up: after syncing main, rebase your feature branch and open a cross-fork PR back to upstream. bb pr create accepts source branch + destination workspace/repo, so you can target the upstream from your fork.

sync-and-pr.sh
#!/bin/bash
set -euo pipefail
UPSTREAM_WORKSPACE="${UPSTREAM_WORKSPACE:?}"
UPSTREAM_REPO="${UPSTREAM_REPO:?}"
FORK_WORKSPACE="${FORK_WORKSPACE:?}" # your workspace
FORK_REPO="${FORK_REPO:?}" # your fork's repo slug
FEATURE_BRANCH="${FEATURE_BRANCH:?}"
TITLE="${TITLE:-Update from $FEATURE_BRANCH}"
# 1. Sync main, then rebase the feature branch onto fresh main.
BRANCH=main ./sync-fork.sh
git checkout "$FEATURE_BRANCH"
git rebase main
git push --force-with-lease origin "$FEATURE_BRANCH"
# 2. Open a PR in the upstream repo, sourced from the fork's branch.
# Bitbucket Cloud uses cross-repo PRs by passing the source as a fork.
bb pr create \
-w "$UPSTREAM_WORKSPACE" -r "$UPSTREAM_REPO" \
-t "$TITLE" \
-s "$FEATURE_BRANCH" \
-d main