I'd like to be able to use git version control with Craft. Is this possible and if it is what is the best approach to ensure that all files/assets and the database are properly synced across local, staging and production servers?

up vote 25 down vote accepted

Matt has a point, this is similar to What's the best practice for handling data migration and organization across development environments?, but that question focuses mainly on how to handle the database (definitely see those answers).

More generally speaking...

Multi-Environment Config

Set yourself up with Multi-Environment Configs in both craft/config/general.php and craft/config/db.php so that you don't have to be updating path settings every time you migrate data between environments.

Be sure to set some Environment-Specific Variables for the site URL and server path for each environment. That way you can use those variables in the control panel settings (the Site URL setting in the Setting → System → General and Assets paths in Settings → Assets → Your asset settings).

Here is a sample general.php file

return array(

    '*' => array(
        'omitScriptNameInUrls' => true,
        'usePathInfo'=> true,
        'cpTrigger' => 'example-admin',
        'allowAutoUpdates' => false,
    ),

    'example.dev' => array(
        'devMode' => true,
        'useCompressedJs' => false,
        'allowAutoUpdates' => true,
        'environmentVariables' => array(
            'siteUrl' => 'http://example.dev/',
            'sitePath' => '/Applications/MAMP/htdocs/example/html/',
        ),
    ),

    'staging.example.com' => array(
        'environmentVariables' => array(
            'siteUrl' => 'http://staging.example.com/',
            'sitePath' => '/var/www/vhosts/staging.example.com/html/',
        ),
    ),

);

And an example db.php file

return array(

    '*' => array(
        'tablePrefix'   => 'craft',
    ),

    'example.dev' => array(
        'server'        => 'localhost',
        'user'          => 'root',
        'password'      => 'root',
        'database'      => 'example_dev',
    ),

    'staging.example.com' => array(
        'server'        => 'localhost',
        'user'          => 'example_staging',
        'password'      => '********************',
        'database'      => 'example_staging',
    ),

);

For more on Multi-Environment Configs see Multi-Environment Workflows on Straight Up Craft

Version control with Git

You can definitely use Git. I version everything except for user file uploads and /craft/storage and it works great.

My master .gitignore file in the root of my project looks like (specific to my setup, YMMV)

.DS_Store

# Node/Sass
node_modules
html/css/public/main.css.map

# Config
dandelion.yml
sftp-config.json
craft/config/db.php

Then in each directory I want to ignore the contents of (craft storage and user uploads) I put a .gitignore file with...

# Ignore everything
*

# But not this file
!.gitignore

And as Matt pointed out in his other comment on your question, do see the answers on the related question What's the best practice for upgrading a versioned Craft site?

  • 1
    You might as well add your .gitignore for posterity, since you've already added lovely multi-environment examples for the general and db configs. :) – Matt Stein Jun 12 '14 at 14:24
  • How would I create templates for each of environments? templates/staging/? – DomK May 2 '15 at 18:01
  • You could have different branches in your git repo, one for each environment. Then deploy the staging branch to staging, the production branch to production, etc. – Alex Kendrick May 2 '15 at 18:45
  • I probably misunderstood your question, Dominik. If Craft had a "path to templates" config setting then you could set that per environment, but I don't think it does. – Alex Kendrick May 4 '15 at 16:41

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.