Every Shopify developer has a version of this story. You make a small change to a theme file. Something breaks. You cannot remember exactly what you changed or where. You try to undo it manually but cannot isolate the problem. Meanwhile the store is live, customers are visiting, and every minute of a broken experience costs real money.
This scenario is entirely preventable. The solution is version control with Git, combined with a structured theme testing workflow that keeps your development, staging, and production environments cleanly separated.
This guide covers the complete setup: how Git works with Shopify themes, how to structure your development workflow, how to use Shopify CLI for local development, how to manage theme environments correctly, and the best practices that professional Shopify development teams use to ship changes confidently without ever breaking a live store.
Why Version Control Matters for Shopify Theme Development
Shopify’s built-in theme editor has a duplicate and publish workflow that provides a basic form of version control. You can duplicate your live theme before making changes and roll back to the duplicate if something goes wrong. This approach works for simple one-off edits but breaks down quickly in any serious development context.
The problems with the duplicate-only approach become apparent the moment more than one developer is working on a theme, or when you are managing multiple rounds of changes across different features. Which duplicate is the current version? Which contains the feature that was half-finished last week? What exactly changed between the version that worked and the version that does not?
Git solves all of these problems by maintaining a complete history of every change made to every file in your theme. Every commit records exactly what changed, who changed it, and when. You can compare any two versions of any file at any point in the project’s history. You can create branches for separate features, merge them when they are ready, and revert any change instantly if it causes a problem.
For Shopify theme development specifically, Git provides three things that are otherwise impossible to replicate: a complete audit trail of every code change, the ability to work on multiple features in parallel without them interfering with each other, and a reliable rollback mechanism that works at the individual file level rather than requiring you to restore an entire duplicate theme.
These capabilities are not just quality-of-life improvements. They are fundamental requirements for any professional development workflow. Our Shopify Custom Development team uses Git-based workflows on every project for exactly this reason.
Understanding Shopify Theme Environments
Before setting up Git, you need to understand how Shopify handles multiple theme environments within a single store, because this is the foundation your version control workflow builds on.
Every Shopify store can have multiple themes installed simultaneously, but only one theme is live to customers at any given time. All other installed themes are in an unpublished state. Unpublished themes are fully functional, can be previewed with a theme preview URL, and can be edited without affecting the live store in any way.
This means you can maintain three separate theme environments within a single store:
Your development theme is where active development happens. It is never shown to real customers. Developers make changes here freely, test features, and iterate without any risk to the live store.
Your staging theme is a near-production copy used for final review and testing before any changes go live. Quality assurance happens here. Stakeholders review designs here. This theme should always represent what the next production release will look like.
Your production theme is the live theme that customers see. Changes only reach this theme after they have been reviewed and approved in staging. It should never be edited directly.
This three-environment structure is the industry standard for professional Shopify development. It prevents the single most common cause of live store breakage: editing the production theme directly.
Setting Up Your Local Development Environment
Installing Shopify CLI
Shopify CLI is the command-line tool that connects your local development environment to your Shopify store. It enables you to sync files between your local machine and a Shopify theme in real time, pull theme files down from your store, push changes up, and run a local development server that reflects changes instantly as you save files.
Install Shopify CLI through npm:
npm install -g @shopify/cli @shopify/theme
Verify the installation:
shopify version
You also need Node.js version 18 or higher and Ruby installed on your machine. On macOS, install these through Homebrew. On Windows, use the official installers from nodejs.org and ruby-lang.org.
Authenticating with Your Store
Authenticate Shopify CLI with your store by running:
shopify auth login --store your-store-name.myshopify.com
This opens a browser window where you log in with your Shopify Partner or store credentials. Once authenticated, CLI stores your session locally so you do not need to re-authenticate for subsequent commands against the same store.
Initializing Git in Your Theme Project
Pulling Your Theme Down Locally
The first step is getting your theme files onto your local machine. Navigate to the directory where you want to store your project and pull down your theme:
shopify theme pull --store your-store-name.myshopify.com --theme THEME_ID
Replace THEME_ID with the numeric ID of your theme. You can find this in your Shopify admin under Online Store and then Themes. The theme ID appears in the URL when you click Customize on any theme.
This creates a local directory with your complete theme file structure:
your-theme/ ├── assets/ ├── config/ ├── layout/ ├── locales/ ├── sections/ ├── snippets/ └── templates/
Initializing Git
Navigate into your theme directory and initialize a Git repository:
cd your-theme git init
Creating a .gitignore File
Before making your first commit, create a .gitignore file to exclude files that should not be tracked. For Shopify themes, this primarily means the config/settings_data.json file, which stores your theme customizer settings and changes frequently with every save in the theme editor:
# Shopify CLI .shopify/ # Theme settings data (customizer settings - managed per environment) config/settings_data.json # Node modules if using build tools node_modules/ # OS files .DS_Store Thumbs.db # Editor directories .vscode/ .idea/ # Build output dist/
The decision about whether to track settings_data.json deserves explanation. This file changes every time anyone saves settings in the theme customizer. If you track it in Git, you will have constant conflicts between environments where settings differ. Most professional workflows exclude it from Git and manage it per-environment. However, if you need settings to be consistent across environments, you can include it but must manage merges carefully.
Making Your First Commit
Add all files and make your initial commit:
git add . git commit -m "Initial theme commit: baseline from production"
This establishes your baseline. Every subsequent change has this commit as its reference point, meaning you can always see exactly what changed from the original state.
Connecting to a Remote Repository
A local Git repository protects you against local mistakes but not against hardware failure or the need to collaborate with other developers. Connect your repository to a remote host.
GitHub is the most widely used option. Create a new private repository on GitHub, then connect your local repository:
git remote add origin https://github.com/your-org/your-store-theme.git git branch -M main git push -u origin main
GitLab and Bitbucket are equally capable alternatives. The choice depends on your team’s existing tooling preferences. All three support the Git workflows described in this guide without any differences in capability for Shopify theme development.
Make your repository private. Your theme code contains your store’s design, custom functionality, and potentially configuration details that should not be publicly accessible.
Branching Strategy for Shopify Theme Development
A branching strategy defines how you use Git branches to organize different types of work and control what gets deployed where. The right branching strategy eliminates the confusion of multiple developers working on the same codebase and ensures that only reviewed, tested code reaches your live store.
The Three-Branch Foundation
Structure your permanent branches to mirror your three theme environments:
main is your production branch. It mirrors exactly what is live on your store. Only merge into main when you are ready to deploy to production. Every commit on main should represent a deployable state.
staging is your pre-production branch. It mirrors your staging theme environment. Features merge here first for integration testing and final review before going to main.
develop is your active development branch. Daily development work happens here and on feature branches that merge into develop.
Feature Branches
For any change beyond a trivial single-file fix, create a dedicated feature branch:
git checkout develop git pull origin develop git checkout -b feature/homepage-banner-redesign
Work on this branch until the feature is complete. Feature branches keep your work isolated so that an incomplete feature never blocks other work from moving forward.
Name branches descriptively using a consistent convention. Common patterns are feature/description for new functionality, fix/description for bug fixes, and hotfix/description for urgent production fixes that need to bypass the normal staging process.
Merging Flow
The normal flow for any change is: feature branch to develop, develop to staging for testing, staging to main for production deployment.
# Merge feature into develop git checkout develop git merge feature/homepage-banner-redesign git push origin develop # When develop is ready for staging review git checkout staging git merge develop git push origin staging # When staging is approved for production git checkout main git merge staging git push origin main
This linear flow ensures that every change passes through testing before reaching production. Nothing goes to main that has not first been reviewed in staging.
Syncing Git Branches with Shopify Theme Environments
The connection between your Git branches and your Shopify theme environments is the operational core of this workflow. Each branch should correspond to a specific theme in your Shopify store.
Setting Up Theme Environments with Shopify CLI
Shopify CLI uses an environments configuration to manage connections between your local repository and specific themes in your store. Create a shopify.theme.toml file in your project root:
[environments.development] store = "your-store-name.myshopify.com" theme = "DEVELOPMENT_THEME_ID" [environments.staging] store = "your-store-name.myshopify.com" theme = "STAGING_THEME_ID" [environments.production] store = "your-store-name.myshopify.com" theme = "PRODUCTION_THEME_ID"
Replace each THEME_ID with the actual numeric ID of the corresponding theme in your Shopify admin.
Add shopify.theme.toml to your .gitignore if it contains sensitive store information, or keep it tracked if you want all team members to share the same environment configuration. Most teams track it, since theme IDs are not sensitive credentials.
Pushing to Specific Environments
With environments configured, you can push to any theme environment directly:
# Push to development theme shopify theme push --environment development # Push to staging theme shopify theme push --environment staging # Push to production theme (use carefully) shopify theme push --environment production
Pushing to production should be a deliberate, reviewed action. Some teams add a confirmation step or require two-person sign-off before any production push.
Running Local Development Against Your Development Theme
For active development, use the Shopify CLI dev server to get real-time sync between your local files and your development theme:
shopify theme dev --environment development
This command starts a local development server that watches your files for changes. Every time you save a file locally, the change syncs to your development theme in Shopify and the browser previewing that theme refreshes automatically. This eliminates the manual upload cycle of traditional Shopify theme development and dramatically speeds up iteration.
A Professional Git Workflow in Practice
Here is how a complete feature cycle looks from start to finish using this workflow:
Step 1: Start from a clean develop branch
git checkout develop git pull origin develop
Always pull the latest before starting new work to ensure you are not building on a stale base.
Step 2: Create your feature branch
git checkout -b feature/product-page-sticky-atc
Step 3: Start the local dev server
shopify theme dev --environment development
Step 4: Make your changes
Edit your theme files locally. Changes sync to the development theme in real time. Test in the browser preview. Iterate until the feature works correctly.
Step 5: Commit your work in logical chunks
git add sections/product-template.liquid git commit -m "Add sticky ATC bar for mobile product pages" git add assets/product-sticky-atc.css git commit -m "Add CSS for sticky ATC bar positioning and animation"
Write commit messages that describe what the change does, not what files were touched. A message like “Add sticky ATC bar for mobile product pages” is useful. “Updated liquid file” is not.
Step 6: Push your feature branch
git push origin feature/product-page-sticky-atc
Step 7: Create a pull request to develop
On GitHub, open a pull request from your feature branch into develop. Assign a reviewer. The reviewer checks the code, leaves comments if needed, and approves when satisfied.
Step 8: Merge and deploy to staging
After approval, merge into develop, then merge develop into staging and push to your staging theme:
git checkout staging git merge develop git push origin staging shopify theme push --environment staging
Step 9: Review on staging
Open the staging theme preview URL and review the feature in the actual Shopify environment. Check on mobile and desktop. Test edge cases. Have a stakeholder sign off if required.
Step 10: Deploy to production
When staging review is complete:
git checkout main git merge staging git push origin main shopify theme push --environment production
Handling Hotfixes
Sometimes a critical bug in production requires an immediate fix that cannot wait for the full develop-to-staging-to-production cycle. Hotfixes have their own flow:
# Branch directly from main git checkout main git pull origin main git checkout -b hotfix/checkout-button-broken # Make the fix, commit it git add . git commit -m "Fix checkout button visibility on mobile Safari" # Push to production immediately after testing git push origin hotfix/checkout-button-broken shopify theme push --environment production # Then merge the hotfix back into main and develop git checkout main git merge hotfix/checkout-button-broken git push origin main git checkout develop git merge hotfix/checkout-button-broken git push origin develop
The critical step that many teams miss is merging the hotfix back into develop. If you only merge into main, the next time develop merges to main it will overwrite your hotfix and the bug will reappear.
Handling Merge Conflicts in Shopify Themes
Merge conflicts occur when two branches have both modified the same lines of the same file. In Shopify theme development, the files most likely to generate conflicts are heavily edited Liquid files like sections/header.liquid, layout/theme.liquid, and busy product or collection templates.
When a conflict occurs, Git marks the conflicting sections in the file:
<<<<<<< HEAD <div class="header-nav"> ======= <nav class="site-navigation" aria-label="Main"> >>>>>>> feature/navigation-redesign
The section between <<<<<<< HEAD and ======= is what exists in your current branch. The section between ======= and >>>>>>> is what the incoming branch wants to replace it with.
Resolve conflicts by editing the file to contain the correct final state, removing all conflict markers, then committing the resolved file:
git add layout/theme.liquid git commit -m "Resolve merge conflict in theme.liquid header markup"
The best way to minimize conflicts is to keep branches short-lived and merge frequently. A feature branch that diverges significantly from develop over two weeks of parallel work will have more conflicts than one that gets merged after two days. Small, frequent merges are less painful than large, infrequent ones.
Theme Backup and Safety Practices
Git provides code-level version control but it does not replace a proper Shopify theme backup strategy. Your Git repository tracks code changes but not content changes made through the Shopify admin: product descriptions, page content, metafield values, and theme customizer settings are all outside Git’s scope.
A complete backup strategy combines Git for code with a Shopify backup app for store data. Our blog on backup apps for Shopify stores covers the best options for protecting your full store data, including content that Git cannot track.
Before any significant theme deployment, manually duplicate your live theme in the Shopify admin. This gives you a one-click rollback option within Shopify itself, independent of Git. Keep the last two or three production theme duplicates at all times.
Comparing This Workflow to Common Alternatives
| Approach | Version History | Multi-Developer Support | Environment Separation | Rollback Speed | Recommended For |
|---|---|---|---|---|---|
| Direct theme editor edits | None | None | None | Manual re-edit | Solo stores, minor text changes only |
| Duplicate before editing | Single snapshot | None | None | One click (limited) | Solo developers, simple stores |
| Git without Shopify CLI | Full history | Yes | Manual | Git revert | Small teams, limited automation |
| Git with Shopify CLI environments | Full history | Yes | Structured | Git revert + push | Professional teams, all stores |
| Git with CI/CD pipeline | Full history | Yes | Automated | Automated rollback | Enterprise, high-frequency deployments |
For most professional Shopify development work, the Git with Shopify CLI environments approach strikes the right balance of structure and simplicity. It does not require DevOps infrastructure but provides all the version control and environment management a serious team needs.
Integrating with CI/CD for Automated Deployments
For teams shipping changes frequently, a CI/CD pipeline automates the process of pushing theme changes to Shopify when code is merged to specific branches. This removes the manual step of running shopify theme push after every merge.
GitHub Actions is the most straightforward option for Shopify theme CI/CD. Create a workflow file at .github/workflows/deploy.yml:
name: Deploy Shopify Theme
on:
push:
branches:
- staging
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Shopify CLI
run: npm install -g @shopify/cli @shopify/theme
- name: Deploy to Staging
if: github.ref == 'refs/heads/staging'
run: shopify theme push --environment staging
env:
SHOPIFY_FLAG_STORE: ${{ secrets.SHOPIFY_STORE_URL }}
SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_STAGING_TOKEN }}
- name: Deploy to Production
if: github.ref == 'refs/heads/main'
run: shopify theme push --environment production
env:
SHOPIFY_FLAG_STORE: ${{ secrets.SHOPIFY_STORE_URL }}
SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_PRODUCTION_TOKEN }}
Store your Shopify API tokens as GitHub secrets rather than in the workflow file. This prevents credential exposure in your repository.
With this pipeline in place, merging to staging automatically deploys to your staging theme and merging to main automatically deploys to production. The deployment happens within seconds of the merge, without any manual intervention.
Liquid Code Quality in a Git Workflow
Version control pairs naturally with code quality practices. When reviewing pull requests for Shopify theme changes, there are specific things worth checking in Liquid code beyond general correctness.
Check for forloop performance issues, particularly deeply nested loops and loops inside loops that query the store’s product catalog. These are among the most common causes of slow theme rendering. Our detailed guide on Shopify Liquid optimization covers the specific patterns to watch for when reviewing Liquid code in pull requests.
Check that new sections follow your theme’s existing schema conventions for settings and blocks. Inconsistent section schemas create confusion in the theme customizer and make future maintenance harder.
Check that any new JavaScript added to assets is appropriately deferred or loaded asynchronously so it does not block page rendering. New scripts are one of the most common causes of performance regression after a theme update.
Our Shopify Speed Optimization Checklist is a useful reference during code review to verify that new theme changes do not introduce performance regressions before they reach production.
Common Mistakes and How to Avoid Them
Committing settings_data.json conflicts. If you track settings_data.json in Git, conflicts between environments are frequent and often confusing. Either exclude it entirely or establish a clear policy about which environment’s settings take precedence during merges.
Working directly on main. Every change, no matter how small, should go through a branch. Direct commits to main bypass the review process and make your history harder to understand.
Vague commit messages. A history full of “fixed stuff” and “updated template” messages provides no audit trail value. Write messages that describe the actual change clearly enough that someone reading the history six months later understands what happened.
Forgetting to pull before branching. Starting a feature branch from a stale version of develop creates unnecessary conflicts when you eventually merge. Always pull the latest before creating a new branch.
Not syncing hotfixes back to develop. This is the most common source of “the bug came back” situations. Any change that goes to production must also merge back into develop, or it will be overwritten by the next deployment.
Pushing directly to production without staging review. The staging environment exists specifically to catch problems before they reach real customers. Skipping it saves five minutes and risks breaking a live store.
These are among the patterns we specifically watch for when conducting a Shopify Site Audit on stores that have had development quality issues.
How KolachiTech Manages Theme Development
At KolachiTech, every theme project uses the Git workflow described in this guide as standard practice. All of our Custom Shopify Theme Development work uses structured branching, environment separation, and pull request reviews before any code reaches a live store.
For clients who want ongoing theme development with professional version control practices built in, our Shopify Maintenance Services team maintains the Git workflow and handles all deployments through a structured, reviewed process. No surprises, no direct production edits, and a complete history of every change ever made to your theme.
If you are dealing with Shopify technical mistakes that have accumulated from years of uncontrolled theme edits, or if you want to set your development workflow up correctly from the beginning, book a free consultation with our development team.
For teams looking at headless approaches where theme version control intersects with framework-level development, our Shopify Hydrogen guide and our blog on serverless functions in Shopify Hydrogen cover how version control practices evolve in a headless context. And our Shopify Webhooks guide covers how event-driven architecture integrates with the kind of custom development work that version control makes safe to build and deploy.
Conclusion
Version control with Git is not an advanced practice reserved for large development teams. It is the baseline standard for any professional Shopify theme development work, whether you are a solo developer or part of a team of ten.
The workflow covered in this guide gives you a complete system: local development with Shopify CLI, three-environment separation between development, staging, and production, a branching strategy that keeps features isolated and deployments controlled, and a pull request review process that catches problems before they reach your live store.
The upfront investment in setting this up correctly is measured in hours. The time it saves, and the store-breaking incidents it prevents, are measured over the entire lifetime of your store.
Set it up once. Use it on every project. Your future self will be grateful every time something breaks in staging instead of in production.
Frequently Asked Questions (FAQs)
1. Do I need Git for Shopify theme development if I work alone? Yes. Version control is valuable even for solo developers because it provides a complete history of every change you have made, the ability to revert any change instantly, and protection against accidental overwrites. The effort of setting up Git is small compared to the time lost investigating and manually reversing an untracked change that broke something in production.
2. What is the difference between Shopify CLI and the Shopify Theme Kit? Shopify Theme Kit was the previous command-line tool for Shopify theme development. Shopify CLI replaced it as the official tool and offers significantly more capability including local development servers with hot reload, environment configuration management, and deeper integration with the Shopify platform. Theme Kit is no longer actively developed and new projects should use Shopify CLI.
3. Can I use this Git workflow with a purchased premium theme? Yes. Most premium themes are purchased as a one-time download, which you can initialize as a Git repository just like a custom-built theme. The key difference is that you will need to manage theme updates from the theme developer carefully, merging their updates into your codebase without overwriting your customizations. A clean Git history makes this significantly easier since you can see exactly what you changed from the original.
4. Should I track config/settings_data.json in Git? Most professional workflows exclude it. This file changes every time anyone saves in the Shopify theme customizer, which generates frequent low-value commits and conflicts between environments that have different customizer settings. Exclude it from Git and manage settings per-environment through the Shopify admin instead.
5. How do I handle a situation where the production theme has been edited directly in the Shopify admin without going through Git? This is a common situation when inheriting a store that did not have version control in place. The solution is to pull the current production theme down as your new baseline commit, establish the Git workflow from that point forward, and accept that pre-Git history is not recoverable. Going forward, all changes go through the workflow. Our Shopify Site Audit service helps identify and reconcile the state of themes that have had uncontrolled edits before establishing a clean development workflow.
6. What is the best way to test theme changes before deploying to staging? Use the Shopify CLI dev server pointed at a dedicated development theme. The dev server provides real-time sync between your local files and the theme, allowing you to test in an actual Shopify storefront environment before committing anything. Test across multiple devices and browsers in development before promoting to staging, so staging review can focus on final approval rather than catching basic functionality issues.
7. How does this workflow change for Shopify Plus stores? The core Git workflow remains identical for Shopify Plus stores. The main additions at the Plus level are that checkout customizations built with Checkout UI Extensions have their own deployment process through the Shopify CLI extensions command rather than through theme push, and that Scripts or Functions used for custom discount and shipping logic also deploy separately. The theme version control workflow described in this guide handles the storefront theme itself, while Plus-specific customizations sit alongside it as separate deployable units within the same repository.
