dbt-проекты живут в git как обычный код. Но workflow аналитика отличается от backend-разработки: ты добавляешь модели, меняешь YAML, иногда исправляешь SQL — а не сервисы и API. Этот урок — про git-практики, адаптированные под dbt.
Feature branch workflow в одном слайде
Один цикл — одна задача. От ветки до merge — обычно 1-3 дня для маленькой модели, неделя для большой.
Шаги цикла
1. Создание ветки
Всегда веткуйся от main:
git checkout main
git pull --ff-only origin main # подтянуть последний main
git checkout -b feature/add-customer-segment
Naming convention для веток (у большинства команд):
feature/<descriptive-name>— новая модель / расширениеfix/<issue>— исправление багаchore/<what>— обновление пакетов, refactoring без logical changedocs/<what>— только обновление descriptions, YAML без SQL изменений
feature/JIRA-1234-add-customer-segment — если у вас Jira/Linear, удобно встраивать тикет в имя.
2. Разработка
В ветке делаешь изменения:
- Новую модель в
models/marts/customer_segments.sql - YAML с tests и descriptions в
models/marts/_models.yml - Если нужны новые seeds — в
seeds/ - Если нужны новые тесты — в
tests/или в YAML
Локально проверяешь:
dbt build --select +customer_segments # собрать и протестировать всю цепочку
Если упало — фиксишь, повторяешь. Когда зелёное — готово к коммиту.
3. Коммиты
Делай частые маленькие коммиты во время разработки:
git add models/marts/customer_segments.sql
git commit -m "feat(marts): add customer_segments model"
git add models/marts/_models.yml
git commit -m "feat(marts): add tests and descriptions for customer_segments"
git add seeds/segment_thresholds.csv
git commit -m "feat(seeds): add segment_thresholds for customer segmentation"
Перед PR можно сделать git rebase -i main или git commit --fixup чтобы привести коммиты в порядок. Но многие команды используют squash & merge в PR — тогда индивидуальные коммиты не важны, важно описание PR.
4. Push и Pull Request
git push -u origin feature/add-customer-segment
Открываешь Pull Request в GitHub/GitLab/Bitbucket. Заполняешь шаблон:
## Что делает этот PR
Добавляет модель customer_segments, которая категоризирует клиентов по lifetime value:
- Bronze: <$100
- Silver: $100-$500
- Gold: >$500
## Lineage impact
- Использует: stg_jaffle__customers, fct_orders
- Изменяется: marts/customer_segments (новая)
- Затрагивает downstream: marts/customer_segments+ -> revenue_by_segment
## Тесты
- not_null(customer_id)
- accepted_values(segment) in ['bronze', 'silver', 'gold']
- unique(customer_id)
## Что проверить ревьюверу
- Логика порогов сегментов в YAML — соответствует ли бизнес-определению?
- Threshold seeds не содержат опечаток?
- В Explorer lineage показывает все downstream корректно?
## Ссылка на задачу
JIRA-1234
5. CI checks
После открытия PR CI автоматически запускает:
dbt build --select state:modified+ --state ./prod-manifest
Это собирает только изменённые модели + их downstream. Результат в PR check’е: зелёный или красный с ссылкой на логи.
Если CI красный — фиксишь, коммитишь, пушишь — checks автоматически перезапускаются.
6. Code Review
Минимум 1-2 reviewer’а смотрят:
- SQL валиден и читаем
- Тесты адекватны
- Documentation присутствует
- Lineage не сломан неожиданно (см. урок 02)
- Изменения соответствуют описанию PR
Они оставляют comments прямо в коде. Ты отвечаешь, фиксишь, пушишь. Цикл повторяется до approval.
7. Merge
Когда есть approval и CI зелёный — merge. Стратегии:
- Squash and merge (дефолт для большинства команд) — все коммиты ветки становятся одним в main.
- Merge commit — сохраняет историю коммитов.
- Rebase and merge — линейная история, без merge commit.
Для dbt-проектов squash чаще всего лучший выбор: одна задача = один коммит в main = одна точка отката.
После merge ветка обычно удаляется (GitHub предлагает кнопку). Локально:
git checkout main
git pull origin main
git branch -d feature/add-customer-segment
Commit-messages для dbt
Большинство команд используют Conventional Commits или подобный формат:
<type>(<scope>): <subject>
[optional body]
[optional footer]
Типы для dbt:
feat— новая модель, новый тест, новая фичаfix— исправление бага в SQL или конфигеchore— обновление пакетов, refactoring без logical changedocs— только descriptions, YAML, README без SQL измененийtest— добавление/изменение тестовrefactor— переименование, переструктуризация, без logical changeperf— оптимизация (например, добавление индексов через post-hook)
Scope (модуль или область):
staging/marts/intermediate— слой моделей<domain>— например,finance,marketing,ops<source>— например,jaffle,stripe
Примеры:
feat(marts): add customer_segments model
fix(staging): handle null updated_at in stg_orders
chore(deps): update dbt_utils to 1.3.1
docs(marts): add column descriptions for revenue_daily
test(staging): add not_null on stg_payments.amount
refactor(intermediate): rename int_payments_joined to int_payments_with_orders
Subject — короткий (50 символов), imperative mood («add», не «added»), нижний регистр.
Body (опционально) — подробности:
feat(marts): add customer_segments model
Сегментирует клиентов по lifetime value:
- Bronze: <$100
- Silver: $100-$500
- Gold: >$500
Использует customer_lifetime_value из fct_orders.
Тесты: not_null, accepted_values, unique.
Closes JIRA-1234
Footer — для cross-references: Closes, Refs, Co-authored-by.
Что НЕ писать в commit
update file.sql— что обновил? зачем? непонятно.wip— work-in-progress коммиты до PR можно, но squash перед merge.fix tests— какие тесты? что было сломано?add stuff— расскажи, что именно за «stuff».
Хорошее commit-message — это future-you благодаря. Через 3 месяца ты будешь искать «когда мы добавили это поле?» через git log --oneline | grep customer_segment. Хороший message — найдёшь сразу.
Pre-commit checks
Pre-commit — это git-hook, который запускается перед созданием коммита. Если что-то не так — коммит не создаётся.
Это middle-уровень тема, но junior полезно знать, что такой механизм есть.
Типичный .pre-commit-config.yaml для dbt-проекта:
repos:
- repo: https://github.com/dbt-labs/dbt-pre-commit
rev: v0.1.0
hooks:
- id: dbt-checkpoint
args: ['--cmd', 'dbt parse']
- repo: https://github.com/sqlfluff/sqlfluff
rev: 3.0.0
hooks:
- id: sqlfluff-lint
args: ['--dialect', 'duckdb']
- id: sqlfluff-fix
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-merge-conflict
Что это делает:
- dbt-checkpoint — запускает
dbt parseлокально, проверяет, что проект валидно компилируется. - sqlfluff-lint/fix — линтер SQL: проверяет именования, форматирование, anti-patterns.
- trailing-whitespace, end-of-file — стандартные housekeeping.
- check-yaml — валидация YAML-синтаксиса.
- check-merge-conflict — ловит незакрытые
7x less-than (HEAD marker)маркеры.
Установка:
pip install pre-commit
pre-commit install # установит git-hook в .git/hooks/
Теперь при каждом git commit запускаются проверки. Если что-то падает — коммит отклоняется, фиксишь, commit ещё раз.
Преимущества:
- Поймать ошибки до push’а, не в CI
- Стандартизированный SQL стиль в команде
- Меньше «починил линтер» PR’ов
Минусы:
- Замедляет каждый commit (~5-10 секунд)
- Иногда ложные срабатывания
В dbt-командах pre-commit становится стандартом. Junior полезно поставить локально даже если команда ещё не настроила.
Что junior должен НЕ делать
- Push directly to main — никогда. Даже маленькие фиксы через ветку и PR.
--forcepush на shared ветки — переписывает историю, плюс ломает чужие checkouts.- Commit
profiles.yml— это креды. Должен быть в.gitignore(см. урок 03). - Commit
target/илиdbt_packages/— артефакты, не код. - Огромные PR: «новая модель + рефакторинг + обновление пакетов» — split на несколько. Review станет невозможным.
- Mix code change и formatting в одном PR — лучше отдельно: один PR с logical change, другой с formatting.
Попробуй сам
В jaffle_shop проекте:
-
Создай ветку
feature/add-customer-tier:git checkout -b feature/add-customer-tier -
Добавь модель
models/marts/customer_tier.sql(можешь сделать любую логику):`{{ config(materialized='table') }}` select customer_id, case when total_spend > 500 then 'gold' when total_spend > 100 then 'silver' else 'bronze' end as tier from `{{ ref('customers') }}` -
Локально проверь:
dbt build --select +customer_tier -
Сделай несколько коммитов с Conventional Commits format:
git add models/marts/customer_tier.sql git commit -m "feat(marts): add customer_tier model" -
Push и открой PR (на свой fork если у тебя нет основного репо).
Чек-лист
- Feature branch workflow:
main-> ветка -> коммиты -> PR -> CI -> review -> merge. - Naming веток:
feature/,fix/,chore/,docs/. - Conventional Commits format:
type(scope): subject. - Типы для dbt: feat, fix, chore, docs, test, refactor, perf.
- Squash & merge — стандарт для dbt-проектов (один коммит в main = одна задача).
- Pre-commit checks: dbt-checkpoint, sqlfluff, check-yaml — поймать ошибки до push’а.
- Никогда не push в main directly. Никогда не commit profiles.yml. Никогда
--forceна shared веток.