Learning Platform
Глоссарий Troubleshooting
Урок 21.01 · 20 мин
Начальный
GitFeature branchesPull RequestsCommit messagespre-commit

dbt-проекты живут в git как обычный код. Но workflow аналитика отличается от backend-разработки: ты добавляешь модели, меняешь YAML, иногда исправляешь SQL — а не сервисы и API. Этот урок — про git-практики, адаптированные под dbt.

Feature branch workflow в одном слайде

Feature branch для dbt-аналитика

Один цикл — одна задача. От ветки до merge — обычно 1-3 дня для маленькой модели, неделя для большой.

main (актуально prod)git checkout main
feature branchgit checkout -b feature/add-customer-segment
commitscommit -m '...'
push & open PRgit push origin HEAD
CI checkdbt build --select state:modified+
review2+ reviewers approve
mergesquash & merge to main

Шаги цикла

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 change
  • docs/<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 change
  • docs — только descriptions, YAML, README без SQL изменений
  • test — добавление/изменение тестов
  • refactor — переименование, переструктуризация, без logical change
  • perf — оптимизация (например, добавление индексов через 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 должен НЕ делать

  1. Push directly to main — никогда. Даже маленькие фиксы через ветку и PR.
  2. --force push на shared ветки — переписывает историю, плюс ломает чужие checkouts.
  3. Commit profiles.yml — это креды. Должен быть в .gitignore (см. урок 03).
  4. Commit target/ или dbt_packages/ — артефакты, не код.
  5. Огромные PR: «новая модель + рефакторинг + обновление пакетов» — split на несколько. Review станет невозможным.
  6. Mix code change и formatting в одном PR — лучше отдельно: один PR с logical change, другой с formatting.

Попробуй сам

В jaffle_shop проекте:

  1. Создай ветку feature/add-customer-tier:

    git checkout -b feature/add-customer-tier
  2. Добавь модель 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') }}`
  3. Локально проверь:

    dbt build --select +customer_tier
  4. Сделай несколько коммитов с Conventional Commits format:

    git add models/marts/customer_tier.sql
    git commit -m "feat(marts): add customer_tier model"
  5. 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 веток.
GitHub Flow: полный разбор GitHub Actions для dbt-проекта
Проверка знанийKnowledge check
Ты добавил модель revenue_by_segment, использующую новую модель customer_segments, плюс обновил dbt_utils в packages.yml. Стоит ли это сделать одним PR или разделить? Аргументируй.
ОтветAnswer
Разделить на ДВА PR. Причины: 1) Atomic change — каждый PR должен делать одно. Если один PR содержит и новую модель И обновление пакета, и при revert придётся откатывать оба. 2) Reviewability — обновление пакета требует другого внимания (changelog dbt_utils, breaking changes), новая модель — фокус на бизнес-логике и SQL. Разные ментальные модели для review. 3) Stability — обновление пакета может неожиданно сломать другие модели в проекте, у которых dbt_utils как dependency. Если это в одном PR с новой моделью, найти причину сложнее. План: PR1 'chore(deps): update dbt_utils to 1.3.1' — узкий, обновляет только packages.yml и lock-файл. CI прогоняет full build, проверяет, что ничего не сломалось. После merge — PR2 'feat(marts): add customer_segments and revenue_by_segment' — две связанные модели на новую функциональность. Связаны логически, можно в одном PR. Если они довольно независимы — можно ещё разделить.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 6. Что НЕ должно происходить в feature branch workflow для dbt-проекта?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 3