Branches and theme sync
How theme editor edits get back into git, and how to avoid overwriting a merchandiser's work.
Branches and theme sync
Two systems write to this theme. Developers write code through git. Merchandisers write settings through the Shopify theme editor, straight to the live theme, with no branch and no review.
A GitHub Action keeps the second set of changes from being lost.
Branches
| Branch | Role |
|---|---|
main | Default branch. Pull requests target it |
production | Receives automated pulls from the live Shopify theme |
main-v6.7.x | Release branches, named for the version in package.json |
| Numbered feature branches | One per ticket, for example 4-ba-115-fx-auhk-update-gift-cards-page |
Feature branches follow <issue-number>-<ticket>-<short-description>, which ties a branch to its GitHub issue and its
ProWorkflow job.
What the theme-pull workflow does
.github/workflows/theme-pull.yml runs on four triggers: a repository_dispatch with the theme_update event type, a
manual run, a daily schedule at midnight UTC, and a push to master.
When it runs it:
- Verifies
client_payload.repomatches this repository, so one webhook proxy can serve several stores without crossing them. - Checks required configuration is present and fails with a clear message when it is not.
- Checks out
production, creating it if it does not exist. - Installs the Shopify CLI.
- Runs
shopify theme pullagainst the live theme. - Commits any changes as
chore: pull theme from shopify on theme updateand pushes toproduction.
The workflow reads this configuration.
| Name | Kind | Value |
|---|---|---|
SHOPIFY_CLI_THEME_TOKEN | Secret | A Theme Access token for the store |
SHOPIFY_FLAG_STORE | Variable | The myshopify domain |
SHOPIFY_FLAG_LIVE | Variable | Must be true, which makes the pull target the live theme |
The workflow writes to production and nowhere else. Nothing merges it into main automatically.
What a pull changes
A pull almost always changes these three.
config/settings_data.json, which holds every theme setting's saved value.
templates/*.json, which hold each page's section layout and per-section settings.
sections/*.json section groups, when a merchandiser edits a header or footer group.
Occasionally an app writes a snippet back. Discount Ninja and Boost both do this, which is why several of their files
are listed in .prettierignore.
The rule
Merge production into your branch before you push a theme deployment.
git fetch origin
git merge origin/productionSkipping this overwrites every theme editor change made since your branch diverged. The failure is quiet. Nothing errors, and the first sign is a merchandiser asking why their homepage reverted.
The recent history of this repository shows the pattern in use. Commit 98126f4 is a merge of production into a
feature branch before a release.
Resolving a conflict in a settings file
Conflicts in config/settings_data.json and templates/*.json are common. Shopify writes these files, so resolving
them rarely needs a line-by-line merge.
Take the production side for any hunk you did not deliberately change. It holds what the live store currently has,
which is what merchandisers expect to keep.
Take your side only for settings your change introduced, such as a new key you added to settings_schema.json.
When a conflict is large or the file will not parse afterwards, take production wholesale and reapply your setting
through the theme editor after deploying:
git checkout --theirs config/settings_data.json
git add config/settings_data.jsonVerify the result parses before committing:
python3 -m json.tool config/settings_data.json > /dev/nullWhy theme editor sync is on during development
shopify.theme.toml sets theme-editor-sync = true for both environments, so shopify theme dev pulls theme editor
changes into your working copy while it runs.
That means git status can show changes to config/settings_data.json and templates/*.json that you did not make.
Review them. Committing them is sometimes right, when you want your branch to carry the current live settings, and
sometimes wrong, when it drags an unrelated in-progress merchandiser edit into your pull request.
reconciliation-strategy = "keep-local" means your local copy wins when both sides changed the same file. It protects
your work and discards theirs locally. The canonical copy is still on the store, so nothing is permanently lost, but do
not treat your local settings file as authoritative.
Setting the sync up on a new store
The README has the full setup. In short:
- Create and push a
productionbranch. - In GitHub, under Settings, Actions, General, Workflow permissions, select Read and write permissions.
- Add the
SHOPIFY_CLI_THEME_TOKENsecret, generated through the Shopify Theme Access app. - Add the
SHOPIFY_FLAG_STOREandSHOPIFY_FLAG_LIVEvariables. - Wire a Shopify
themes/updatewebhook to arepository_dispatchcall through a small proxy, so every theme editor save triggers a pull.
If production is a protected branch, the default GITHUB_TOKEN cannot push to it. Either allow github-actions[bot]
past the protection, or swap in a personal access token or deploy key.
Source map
| Concern | File |
|---|---|
| Theme pull workflow | .github/workflows/theme-pull.yml |
| Store and environment configuration | shopify.theme.toml |
| Files excluded from theme pushes | .shopifyignore |
| Files excluded from Prettier | .prettierignore |