Branching & Commits
TL;DR: How Git branches map to Shopify themes, and what happens when someone edits in the admin.
The two-way sync — this is the part that surprises people
Section titled “The two-way sync — this is the part that surprises people”Shopify’s GitHub integration works in both directions. It’s not a one-way street. Once a branch is connected to a theme, two things happen:
- Pushing to the branch updates that theme in Shopify automatically.
- Editing the theme in Shopify admin (using the theme editor, the code editor, or even a merchant’s own customizations) automatically commits those changes back to the branch, authored by the
shopifybot.
So imagine a designer changes a color setting in the theme editor. Without realizing it, they just added a commit to your Git history. Don’t panic when you see commits made by shopify show up in your log. This is expected behavior, not a security problem.
Branch strategy
Section titled “Branch strategy”| Branch | Connected to | Purpose |
|---|---|---|
main | Published (live) theme | Only merges that have passed review and QA |
develop (or per-feature branches) | An unpublished development theme | Work in progress, safe to preview without affecting the live store |
Once you disconnect a branch from a theme, you can never reconnect it to that same theme again. Reconnecting always creates a brand new theme instead. Keep this in mind before you rename or clean up branches.
| ✅ Do | ❌ Don’t |
|---|---|
Connect main to the live/published theme only after it’s been reviewed | Connect a feature branch directly to the live theme “just to test something quickly” |
| Disconnect a branch deliberately, knowing it creates a new theme on reconnect | Disconnect and reconnect a branch casually, assuming it picks up where it left off |
| Keep feature branches short-lived | Let a development-theme-connected branch sit for weeks, drifting further from main |
Branch naming convention
Section titled “Branch naming convention”Every branch off main (or develop) follows one format:
namespace/branch-name/collaborator-id| Segment | What it is | Example |
|---|---|---|
namespace | The same prefix you use in a commit message: feat, fix, chore, docs, refactor, or test | feat, fix |
branch-name | A short, lowercase description of the work, written with hyphens between words (a style called kebab-case). It’s similar to a commit’s scope, just a bit more detailed | testimonials-section, cart-total-refresh |
collaborator-id | Your GitHub username, lowercase. This is different from the Shopify store “collaborator” access covered in Prerequisites & Setup. Here, it just shows who’s working on the branch | jsmith, agarcia |
Full examples:
feat/testimonials-section/jsmithfix/cart-total-refresh/agarciachore/bump-theme-check/jsmithdocs/prerequisites-update/agarciaThe namespace matches the commit type on purpose. A feat/ branch should only produce feat(...) commits, and it should turn into a PR for one feature, not a mix of different things. Sometimes a branch’s real work stops matching its namespace. For example, a fix/ branch might grow into a full feature. When that happens, split it into two branches instead of just renaming it.
The collaborator ID goes last, not first. This way, branches sort and group by namespace in most Git tools and in the git branch output. Every feat/ branch sits together, then every fix/ branch, and so on. That’s more useful than grouping by person when you’re scanning a list of open branches.
| ✅ Do | ❌ Don’t |
|---|---|
feat/quote-block/jsmith | jsmith-quote-block (no namespace, no structure) |
fix/newsletter-a11y/agarcia | fix/Newsletter_A11y/AGarcia (mixed case, underscores instead of hyphens) |
| One focused change per branch | feat/several-unrelated-fixes/jsmith (split into separate branches instead) |
| Your actual GitHub username as the collaborator ID | Initials (js, ag), since these collide as the team grows. Usernames don’t |
Commit conventions
Section titled “Commit conventions”We use Conventional Commits:
feat(sections): add testimonials section with quote blocksfix(accessibility): add missing label to newsletter signup inputchore(deps): bump theme-check to latestPrefixes: feat, fix, chore, docs, refactor, test. The scope, written in parentheses, is the part of the code you touched. It could be a section name, accessibility, deps, or something similar.
More examples, right and wrong
Section titled “More examples, right and wrong”| ✅ Good commit message | ❌ Weak commit message | Why |
|---|---|---|
fix(cart): refresh total_price on quantity change | fix bug | Specific about what and where |
feat(blocks): add nestable "quote" theme block | updates | Says what was actually added |
refactor(product-card): extract snippet shared by grid and search | cleanup | Explains the actual change, not just the category |
Handling shopify-authored commits in your history
Section titled “Handling shopify-authored commits in your history”Admin edits create real commits. That means the Git history on a connected branch will have shopify-authored commits mixed in with your own. This is normal, but it does change how you should work with the branch day to day.
- Don’t casually run
git rebase -ito “clean up” a connected branch’s history. Doing this risks rewriting commits that Shopify’s sync depends on, which can break the connection between your branch and the theme. - When you look at the recent history to understand what changed, expect to see both human commits and
shopify-bot commits. Check both, not just your own. - Sometimes a merchant or designer’s theme editor changes will conflict with the work on your branch. When that happens, fix it like you would fix any other Git conflict. Shopify’s own docs point out that the code editor doesn’t warn you about conflicts, so it’s up to you to notice them and fix them.
Do / Don’t
Section titled “Do / Don’t”| ✅ Do | ❌ Don’t |
|---|---|
Name every branch namespace/branch-name/collaborator-id right from the start. Renaming a branch later to fit this pattern takes much more work than starting with it. | Force-pushing or rebasing a connected branch without thinking about whether Shopify’s sync depends on the existing commit history. |
| Use your real GitHub username as the collaborator ID, not initials. Initials can clash as the team grows, but usernames don’t. | Assuming a branch picks up the same theme after you disconnect and reconnect it. It doesn’t. It creates a new theme instead, which can be a confusing surprise in the middle of a project. |
| Write commit messages that would make sense to someone with no context, six months from now. A message like “fix bug” tells a future reader nothing. | — |
Treat shopify-authored commits as real history, not noise to ignore. They reflect actual changes made to the live theme. | — |
| Avoid rewriting history (using interactive rebase or force-push) on branches connected to a theme. Shopify’s sync needs a steady, unchanged commit history to line up admin-side changes correctly. | — |
Key takeaways
Section titled “Key takeaways”- Only a repo with the standard theme folder structure can be connected. Other folders are ignored.
- Once disconnected, a branch can’t reconnect to the same theme — reconnecting always creates a new one.
- Avoid rewriting history (rebase, force-push) on a theme-connected branch. Shopify’s sync depends on it staying intact.
Further reading
Section titled “Further reading”- Shopify GitHub integration (shopify.dev)
- Conventional Commits (conventionalcommits.org)
- Version control best practices (shopify.dev)