dbt ties environments and deployments to Git branches, so your branching strategy directly affects quality, velocity, and risk.
This article starts from trunk-based development (main-centered) as the default, then walks through when a release branch is needed, design patterns, CI/testing, schema design, and selectors (state:modified) in concrete detail.
In dbt, the Git branch is the primary switch that decides which code will run. In dbt Cloud, a deployment Environment is tied to a single Git branch, and jobs execute against that branch's code. The CLI works the same way — whichever branch you have checked out is what dbt commands run against.
Trunk-based (main-centered) merges small, frequent changes into main and relies on PRs for quality. A release branch bundles changes at a point in time into a fixed "release unit," making it easier to freeze, validate, roll out incrementally, and roll back.
The basic flow is: feature branch → PR review and CI → merge into main → main deploys to production. PR CI uses slim CI (state comparison) to quickly validate only the diff and its dependencies. Deployment is centralized in a production Environment/job that tracks the main branch.
To minimize the gap between production and PR builds, use defer to reference production artifacts (the previous manifest/Run Results), avoiding rebuilds of unchanged models while still validating dependency integrity.
Standard trunk-based flow (PR CI → main deploy)
Minimal slim CI example (CLI, run on PRs)
dbt deps
# Reference the previous production artifacts (location depends on your setup: S3/GCS/DBFS/local, etc.)
dbt build \
--select state:modified+ \
--state path/to/prod_artifacts \
--deferFor day-to-day operations, trunk-based is enough. But a release branch is useful when: you need a bulk cutover aligned with external data sharing or BI publishing; regulators or auditors strongly require reproducibility of "this version"; you have a long-running backfill or schema migration that needs phased rollout; or you need a code freeze during a busy season.
The design principle: once you cut release/*, only pull in the minimum necessary changes, run PR review/CI on the release branch, and either point the production Environment at it temporarily or apply it first in a canary Environment before cutting over. Cut hotfixes from the release branch, cherry-pick them, and back-merge into main to keep drift in check.
| Perspective | Trunk-based | Release branch | Exam angle |
|---|---|---|---|
| Release granularity | Small diffs, continuously | Bundle changes into one release | Small diffs and frequent deploys are the recommended baseline |
| Risk management | Short-lived branches keep risk low | Long-lived branches risk conflicts and drift | Understand the downsides of long-lived branches |
| CI focus | Slim CI on every PR | Freeze and concentrate validation on the release branch | When to use state:modified vs defer |
| Migration strategy | expand → migrate → contract | Phased cutover / canary | Schema changes need a compatibility phase |
| Backfills | Run in stages via separate jobs | Include on the release branch or run in a separate pipeline | As a rule, isolate large-scale processing from the main pipeline |
| Hotfixes | Fix directly on main → deploy immediately | release/hotfix → cherry-pick → back-merge | Design to keep drift small |
Release branch basic operations (example)
# Create a temporary release branch
git switch -c release/2024w42
# Merge only the necessary PRs (keep scope minimal)
# ... code review / merge ...
# Temporarily point the dbt Cloud production Environment at release/2024w42
# or apply changes first in a canary Environment
# Hotfix
git switch -c hotfix/bug-on-release release/2024w42
# After fixing, merge into the release branch and roll out to production
# Back-merge into main to eliminate driftIt is common in dbt to separate environments by schema within the same database. Let branches decide "which code runs" and environments decide "where it deploys." A per-user schema in dev, a shared schema in stg/qa, and a fixed schema in prod is the easiest split to manage.
Align schema naming with your branching strategy by using target.name and custom schemas consistently. For expand/contract migrations, keep the old column around for a transition period to preserve compatibility — this lets you proceed safely whether or not you use a release branch.
A generate_schema_name example (isolating schemas by environment)
{% macro generate_schema_name(custom_schema_name, node) -%}
{% if target.name == 'prod' %}
{{ custom_schema_name or 'analytics' }}
{% else %}
{{ target.name }}__{{ custom_schema_name or 'analytics' }}
{% endif %}
{%- endmacro %}The core of slim CI is state comparison. By diffing against the previous production artifact, it builds and tests only the changed models and their downstream. Combining this with defer resolves unchanged upstream models "as if they exist," dramatically speeding up PR builds.
Even during release-branch operations, use the same selectors and defer on the release branch, and separate migration jobs (backfills) by tag. Design CI so that contracts and tests (unique/not_null/relationships) always run on the PR.
selectors.yml and example commands
# selectors.yml
selectors:
- name: pr_modified
definition:
method: state
value: modified
children: true
# Example (PR CI)
dbt build --select @pr_modified --state path/to/prod_artifacts --defer
# Example (production)
dbt build --select state:modified+ --state path/to/prod_artifactsThe Analytics Engineer exam is less about branching strategy itself and more about PR-centric development, when to use state/defer, quality gates via contracts/tests, and backward-compatible migrations (expand/contract). For release branches, the key is recognizing the exceptional cases where they are genuinely needed.
Typical mistakes include letting long-lived release branches drift far from main, mixing backfills into the main pipeline so PRs cannot pass, and breaking downstream with schema changes. All of these can be avoided through small diffs, tag-based isolation, state usage, and phased migrations.
Minimal contracts and tests example
models:
- name: fct_orders
config:
contract: true
columns:
- name: order_id
data_type: int
tests:
- unique
- not_null
- name: customer_id
data_type: int
tests:
- relationships:
to: ref('dim_customers')
field: customer_idAnalytics Engineer
問題 1
On an internal analytics platform, you want to ship small daily improvements quickly, validate only the diff on PRs, and update only the affected models in production. Meanwhile, a one-off large-scale backfill is scheduled next month. Which branching strategy and operating model is best?
正解: A
For day-to-day work, the baseline is trunk-based with small continuous releases. Use slim CI (state/defer) on PRs and differential deploys via state:modified+ in production. Isolate the large-scale backfill in a dedicated job so it does not block the main delivery flow. Avoid release branches and long-running freezes unless there is a hard requirement for them.
What is slim CI, and how do you set it up in dbt?
Slim CI is a technique that compares against the previous artifact and only builds/tests the changed models and their downstream dependencies. Define state: modified in selectors.yml and run something like dbt build --select state:modified+ --state <previous artifacts> --defer. It is highly effective for speeding up PR builds.
How should seeds and snapshots be handled on a release branch?
When the impact is broad, separate jobs by tag (for example release_only, migrate) and make sure they can be re-run idempotently. Use state/defer on the release branch for validation as well, and reduce risk during the production cutover with canary or phased rollouts.
Does the branching strategy change depending on the data warehouse (Snowflake, Databricks, etc.)?
The fundamental approach does not change. Regardless of the warehouse, dbt is controlled via Git branches and Environments. The differences lie in how you isolate schemas/catalogs and design permissions. Adjust per-environment schema naming, runner permissions, and cost/concurrency policies, and the same strategy applies.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
dbt Models: SQL-Defined Transformation Units (2026)
Model fundamentals — SELECT-based definitions, naming, refs,...
dbt Analytics Engineering Exam: Complete Guide (2026)
Pass the AE Certification — scope, weighting, sample questio...
dbt Cloud vs dbt Core: Feature & Cost Comparison (2026)
Honest comparison of dbt Cloud vs. dbt Core — IDE, scheduler...
dbt Project Structure: models/seeds/macros Layout (2026)
Recommended dbt project layout — models, seeds, macros, snap...
dbt_project.yml Explained: Every Config (2026)
Every dbt_project.yml setting that matters — paths, vars, ma...