Common Workflows

End-to-end walkthroughs of the most common Environment Sync workflows, from promoting changes to production to recovering a drifted environment and standing up a new one.

These workflows cover most day-to-day use of Environment Sync: promoting changes to production (all of them, or just the ones that are ready), re-aligning an environment after out-of-band changes, and standing up a new environment from the committed files. The mechanics behind each step live in Pulling, Diffing & Pushing, and CI & Automation.

Promote changes from development to production

You model in the Data Studio on a development instance. Production only ever receives what git has reviewed.

  1. Make your changes on the development instance: collections, fields, flows, permissions.
  2. Pull them into the repository and commit:
    d6s sync pull --from dev
    git add directus/
    git commit -m "Add author bio fields"
    

    The files are deterministic, so the commit shows your change and nothing else. On a development instance other people also use, a scoped pull (--collections posts, or a resource flag like --flows) keeps their in-progress work out of your diff.
  3. Open a pull request. Reviewers read the change as plain JSON diffs. A CI check can add the target's view of the same change:
    d6s sync diff --to production --json
    
  4. On merge, apply:
    d6s sync push --to production --yes
    

    The default merge mode creates and updates but never deletes. A second run reports nothing to push.
Removals need mirror. A change that deletes a field or a record does not propagate under merge. Push with --mode mirror and pass its deletion gate, and run a full pull first so the mirror applies current state, not a stale tree.

Promote only the changes that are ready

A shared development or staging instance usually carries more than one piece of work at a time. Say the posts changes are ready to ship, and half-finished authors changes are not. Scope the pull to what ships:

d6s sync pull --from staging --collections posts

What that pull just did:

  • The posts schema files were rewritten with the new state.
  • The authors schema files were not touched. They still hold what the last full pull captured, which is the state production already runs. The half-finished authors work never entered the repository.
  • Configuration resources refreshed too, because a collections scope only narrows schema. Nothing changed there, so those files came back byte-identical and git status shows only the posts files. If a flow had also changed on staging, its file would show up here; hold it back with --no-flows on the pull.

Commit, then diff and push as usual:

git add directus/
git commit -m "Add post fields"
d6s sync diff --to production
d6s sync push --to production

A push always applies the whole committed folder. The posts change applies. The authors files already match production, so nothing happens there. And since the unfinished authors work is not in the repository, it cannot ship, no matter what state staging is in.

For a configuration-only change, flip the scope: select the resource type and skip schema.

d6s sync pull --from staging --flows --no-schema

The What a pull touches table shows exactly which files each combination refreshes and which it leaves alone.

Selection is by collection and resource type, not by record.--collections posts can separate finished posts work from unfinished authors work, but two changes inside the same collection travel together, and --flows takes every flow, not just one. If unrelated work shares a collection or a resource type, ship it together or wait. And while the committed tree holds a partial picture, avoid mirror: it would apply the stale remainder too.

Rebase an environment from production after drift

Sometimes production changes outside the deployment path, usually an urgent manual fix. Staging and the repository no longer reflect reality. Bring the fix into git, then re-align the lower environment. This is what mirror is for: converging an environment to the committed state exactly.

  1. Pull the full state from production. The out-of-band change appears as an ordinary git diff, which is your record of what the hotfix actually was:
    d6s sync pull --from production
    git diff
    git add directus/
    git commit -m "Adopt production hotfix"
    
  2. Preview what re-aligning staging would mean:
    d6s sync diff --to staging
    

    Read the deletions closely. Anything that exists only on staging and falls inside the sync's scope is on the list.
  3. Converge staging to the committed state:
    d6s sync push --to staging --mode mirror
    

    Interactively, the push names the losses and asks you to type the profile name; in automation it requires --dangerously-allow-delete. See deletion gates.
Mirror removes staging-only work in scope. If staging holds experiments you want to keep, pull that work into a branch first, or use merge and clean up by hand.

Stand up a new environment

Going from an empty instance to a working copy of your project's shape:

  1. Provision a fresh Directus instance and create its admin account as usual.
  2. Add a profile for it:
    d6s profile add staging --url https://staging.example.com --token <token>
    
  3. Preview, then push the committed files:
    d6s sync diff --to staging
    d6s sync push --to staging
    

    Schema applies first, then the configuration records import.
  4. Commit the updated id_map.json. The push records which target record each committed record became, and that map is how every later push updates records instead of duplicating them.

Two things to expect on a first push:

  • Identity questions. If the target already holds records the CLI cannot tell apart from the committed ones (two policies named "Administrator" is the classic case), an interactive push asks you to choose. Answer once, commit the map, and the questions do not come back. See record identity.
  • Secrets stay behind. Stripped values (API keys in settings, concealed fields, flow credentials) never travel with the files. Set them on the new instance directly.
Push the whole committed tree to a fresh target, not a scoped slice. A partial snapshot whose relations point at collections outside the scope can fail to apply on an instance that has nothing else yet. The pull warns about these references when it writes the files.

Get once-a-month release notes & real‑world code tips...no fluff. 🐰