Skip to main content

Branch strategy

App repositories develop on test and release on main. They stay in step by cherry-pick, never by merging test into main.

The rule​

feature work → test → CI deploys :test → verified → cherry-pick onto main → CI deploys :prod

A merge is not a shortcut here. It is a production identity change.

Why, specifically​

gstv-website/src/Firebase/FirebaseConfig.js selects its Firebase project by branch:

BranchFirebase project
maingrey-screen-tv (production)
testgreyscreen-test-5fb86 (test)

public/firebase-messaging-sw.js carries the same project. Both native apps follow a build-variant equivalent in app.config.ts.

Merging test into main would carry the test project into production and silently regress every user's identity. This has happened before; the fix is recorded in the history, and the branch-selection pattern is deliberately kept.

gstv-website/.env.production separately carries a live publishable Stripe key, while its comments still mention a sandbox. The comments are stale. Inspect the key prefix; never copy the value.

Branches by repository​

RepositoryDevelopmentReleaseNotes
gstv-websitetestmainBranch-selected Firebase
greyscreen-webviewtestmainIdentity comes from the native shell
greyscreen-expo-webviewtestmainVariant-selected Firebase; store builds from android / ios
gstv-tvtestmainVariant-selected Firebase; EAS branches
gstv-admin-webtestmainTalks to the admin API only
gstv-customer-apitestmainProduction main lags unless cherry-picked
gstv-admin-apitestmainSame; artwork work was cherry-picked
gstv-vpstestmainmain has no deploy job
gstv-multimediatestmainTest auto-deploys
gstv-migration—mastermaster, not main
vps-reverse-proxyone branch per VPSsameThe branch is the deployment

Several repositories carry long-lived firebase-migration branches. They are historical; do not treat them as release branches.

The checked-out branch is not the release branch​

Verification on 2026-10-22 found main checked out in only five of the app/API repositories. Before you assume what is deployed, read the branch list, not the working tree:

git for-each-ref --format='%(refname:short) %(objectname:short)' refs/heads
git log --oneline -5 origin/main

Cherry-picking safely​

  1. Land the change on test and verify it there.
  2. Note the commit hash.
  3. On main, cherry-pick that hash, not the branch.
  4. Resolve conflicts by keeping main's branch-selected identity files.
  5. Confirm the diff does not include FirebaseConfig.js, firebase-messaging-sw.js, app.config.ts, or a .env file that belongs to the other environment.
  6. Push main; production deploy runs behind its environment approval.

If a cherry-pick touches a queue contract, deploy the worker image first — the branch order does not change the consumer-before-producer rule.

Known divergence today​

AreaReality
Test stackPoints at the production Firebase project. Only buckets are separate.
Worker imagesTest :test is coherent; production's Artifact Registry tag is not built by any repo.
gstv-db-coreCanonical and both API mirrors have diverged. Do not run sync.sh.
Pairing contractThree copies, no canonical source, no syncing script that exists.

These are not branch problems, but they are the reason a "just merge and see" instinct is expensive here.

Commit style​

Conventional prefixes are used consistently in the history — feat(scope):, fix(scope):, merge: — and the scope names the surface (billing, firebase, title, catalogue). Match it; the history is the only changelog.

Next: Security notes.