/ open source

Managing Drupal 8 Config With git Within Teams With Multiple Developers

How do you manage syncing schema changes between developers in a repeatable, simple way?

In Drupal there's a system known as configuration management (export/import) for managing site configuration. However, you quickly realise it's not complete enough to use it alone to manage a multi developer scenario without some thought.

At the time of writing Drupal is celebrating it's 17th Birthday today, and is more powerful than ever, but with such power inevitably comes complexity and this shows in the time investment required to understand configuration management. It's not broken, it's simply complex.

Managing A Drupal 8 Database Changes Across Teams

  • We need to version control the database across teams
  • Deploy schema changes without fear, have ability for rollback
  • Other projects have some interesting solutions which work very well

What are other projects doing to solve this?

We're used to working with 'migrations' using Laravel migrations and we've found it really simple to get a team of developers smoothly managing schema changes during development.

It essentially works in the following way:

  1. We use the console program artisan to generate a new migration
  • Artisan expects a human readable name of the schem change made Timestamps schema change
  • Artisan pre-fixes the migration with a time-stamp
  • Artisan generates a boilerplate migration code (php) in a folder named migrations.
  • The developer writes an up() and down() function to perform the alteration (e.g. rename a table column)
  • The developer performs php artisan migrate and the outstanding migration is ran against the database.
  1. It's pushed to the repo, so all developers can use it seemlessly

The beauty of the up() and down() functions is that this allows the developer to rollback migrations forward or back schema changes as they wish. But most importantly it's simple and you can teach it in less than 30 minutes, and have a team pushing and pulling schema changes without fear of loosing config changes.

It's powerful and easy.

Most importantly Laravel Migrations is simple and you can teach it in less than 30 minutes. You can have a team pushing and pulling schema changes without fear of loosing config changes. Drupal 8 needs the convenience of Laravel's Migrations mixed with Drupal's powerful ecosystem because teams with less friction in development are happier, and less stressed, and keen to experiment.

It's a very convenient way of working, simple, and developers simply run git pull origin <branch-name> and then run php artisan migrate to perform any database schema updates they were behind on. There's also Doctrine Migrations which takes a different approach by making changes directly to your entity classes. asvae has written a comparison of Laravel & Doctrine migrations.

It's not that simple on Drupal. The configuration management system exports are not time stamped, nor are they migrations defined as code such as they are in Laravel (maybe this should be a thing?).

Instead, the result of a drupal config:export are lots of .yml files in your config/sync directory which are taken out of the active config in your database. This is a reflection of that database's active config- but it will blast over your current config (deleting your work) if you blindly run drupal config:import on your local development environment. You need to preserve, merge and manage your configs using a combination of git and Drupal console. Luckily this can be turned into a repeatable pattern.

How to manage migrations in Drupal 8

So what can we do?

First, accept that Drupal is more complex that other systems. There are many abstractions which Drupal has built in which other systems simply have no concept of out of the box. This is similar to python's 'batteries included' motto. A good Drupal example are Bundles and Collections; sound complicated but really Drupal is helping you model your data (polymorphism in Drupal) before you knew you needed it; Drupal can often seem overly complex for these reasons, when actually it's well thought through.

Preserve Site Configuration Between Developers Using git & Drupal Console

  1. On your local environment make a change (e.g. add a description to a content type)
    • Making a change like this would trigger a change to your active config which must be exported, committed and pushed to your remote (step 2)
  • Export your config (vendor/bin/drupal config:export)

    • Drupal console pulls your active config from the database, and serialises it into .yml in your config/sync directory.
  • Review & add changes to config

    • git status to see which files have changed
    • git diff <fileName> to show the exact changes per file (if you want)
    • git add <fileName> to stage the changes for committing
  • Commit changes (git add)

    • This has the effect of preserving your config and giving you somthing to rollback to (using git checkout <commit-hash>) later if you need to recover from a mess.
  • Pull from master (git pull origin <branchName>)

    • Assuming other developers have pushed to the remote, you pull changes down from your remote, which may contain schema alterations of their own. Git will attempt to merge these. If it fails, resolve the merge conflict it's not scary!
  • Review changes

  • composer install Other Drupal modules may have been added to the project, so composer install is needed to fetch these. Otherwise you'll get the error "Unable to install the module since it doesn't exist",

  • Import (if there were any) changes your fellow devs have made which includes yours automatically because of step 5 which preserves your changes. (vendor/bin/drupal config:import)

    • If there were no changes from your fellow developers you'll see the message "[OK] There are no changes to import.", otherwise, it will import both your changes and the rest from the remote.
  • Rebuild cache vendor/bin/drupal cr all

  • Push to master (git push origin master)

  • Switch to staging / production

  • git pull origin master

  • vendor/bin/drupal config:import

  • Rebuild cache vendor/bin/drupal cr all
    This is being expanded to include:

  • What about preserving master site config changes

    • e.g. If your client is allowed to alter the site name, this alters the site configuration and must be preserved
  • Using Git Hooks to automate the process