Why this matters
As a BI Analyst, your SQL models power dashboards, KPIs, and decisions. When logic changes, stakeholders need to know what changed, why it changed, and how to roll back if needed. Tracking changes gives you:
- Auditability: every SQL change is documented with a reason.
- Safe iteration: test changes on a branch before merging to production.
- Clear reviews: diffs show exactly what lines changed.
- Fast rollback: revert to a previous version if metrics look off.
Who this is for
- BI Analysts and Analytics Engineers creating SQL models for reporting.
- Data-savvy Product/Operations analysts who deliver recurring SQL updates.
- Anyone new to Git who wants to manage SQL safely and clearly.
Prerequisites
- Basic SQL: SELECT, JOIN, GROUP BY, CASE.
- Basic Git: git init, add, commit, status.
Quick self-check
- Can you write a query that aggregates revenue by month?
- Can you make a commit and view git log?
Concept explained simply
Think of SQL models as source code. Each meaningful change should be a commit with a short, clear message. You compare versions with a diff, review on a branch, and merge when ready. Structural changes to warehouse tables are tracked with migration scripts (e.g., ALTER TABLE) plus model updates.
Mental model
Picture your SQL models like a Google Docs document with version history. Git is the version history: every change is labeled, comparable, and reversible. Branches are draft copies; main is the approved document.
Core workflow (step-by-step)
- Create a branch for your change (e.g., feature/add-new-metric).
- Make a focused change in a .sql file. Format consistently to keep diffs clean.
- Stage and commit with a clear message describing intent, scope, and why.
- Run queries/tests locally or in a staging environment.
- Open a review (pull request) for feedback. Merge when approved.
- If something breaks, roll back using Git (revert or restore a file to a prior commit).
Tips for clean diffs
- Keep one logical change per commit.
- Use consistent formatting and casing to avoid noisy diffs.
- Avoid reordering columns or lines unless necessary—order changes create large diffs.
Worked examples
Example 1 — Modify metric logic in a SELECT model
Goal: Update revenue definition from excluding refunds to net of refunds.
Before (models/revenue.sql):
SELECT
order_id,
amount AS revenue
FROM orders
WHERE status = 'paid';
After:
SELECT
o.order_id,
o.amount - COALESCE(r.refund_amount, 0) AS revenue
FROM orders o
LEFT JOIN refunds r ON r.order_id = o.order_id
WHERE o.status = 'paid';
Commit message:
feat(revenue): compute net revenue by subtracting refunds
Reason: Align metric with Finance definition; impacts KPI dashboards.
What the diff highlights: new LEFT JOIN and a changed revenue expression.
Example 2 — Add a column via migration + update model
Goal: Add sales_channel to orders and expose it downstream.
Migration (migrations/202501_add_sales_channel.sql):
ALTER TABLE orders ADD COLUMN sales_channel VARCHAR(50);
Model change (models/orders_clean.sql):
SELECT
order_id,
customer_id,
amount,
sales_channel
FROM orders;
Two commits keep intent clear:
chore(schema): add sales_channel to orders table
feat(orders_clean): select sales_channel for downstream models
Example 3 — Rename a derived table safely
Goal: Rename monthly_revenue to rev_monthly while preserving consumers.
Step 1 (backward-compatible view):
-- migration
CREATE OR REPLACE VIEW monthly_revenue AS SELECT * FROM rev_monthly;
Step 2 (update references over time) and then remove the legacy view.
Commits:
feat(model): create rev_monthly and compatibility view monthly_revenue
refactor(downstream): switch references to rev_monthly
chore(cleanup): drop compatibility view monthly_revenue
Common mistakes and self-check
- Mixing multiple unrelated changes in one commit. Self-check: Can you summarize the change in one sentence? If not, split it.
- Noisy diffs due to reformatting + logic changes together. Self-check: Commit formatting separately.
- Forgetting migration scripts for schema changes. Self-check: Any new/removed/renamed column? If yes, add a migration.
- Vague commit messages. Self-check: Does the message say what changed and why?
- No rollback plan. Self-check: Can you point to the exact commit to revert if KPIs spike?
Exercises
These mirror the tasks in the Exercises section below. You can complete them locally with Git or in any Git-enabled environment.
Exercise 1 — Track a logic change in a SQL model (ex1)
- Create a repo folder and a file models/revenue.sql with a simple revenue query.
- Commit it. Change the logic to net revenue and commit again.
- Use git diff and git log to verify changes and messages.
Checklist
- Repo initialized
- First commit created
- Logic updated and second commit created
- Diff shows only the intended lines changed
Exercise 2 — Add a column with migration + update model (ex2)
- Write a migration to add sales_channel to orders.
- Update a model to select the new column.
- Make two separate commits and review diffs.
Checklist
- Migration file exists
- Model updated to select new column
- Two commits with clear messages
- Diffs are clean and understandable
Practical projects
- Metric evolution tracker: Build a folder with a sequence of commits showing how a KPI definition evolves; document impact notes in commit bodies.
- Schema change cookbook: Create a repo with example migrations (add/rename/drop columns) and corresponding model updates.
- Rollback simulation: Introduce a bug in a branch, merge it, then practice reverting the commit and verifying the fix.
Learning path
- Before this: Git fundamentals, basic SQL modeling.
- Now: Tracking changes in SQL models (this lesson).
- Next: Branching strategies, code review practices, adding tests and data quality checks.
Mini challenge
Your stakeholder requests a new discount logic. Make a branch, implement the logic change in the discounts model, commit with a clear message, and prepare a short note in the commit body describing expected KPI impact and how to validate it. Keep the diff minimal and focused on the logic change.
Next steps
- Adopt a consistent commit style: type(scope): summary + why.
- Practice small, focused commits and clean diffs.
- Introduce lightweight reviews for every model change.
Progress and quick test
Take the quick test to check your understanding. The test is available to everyone. Only logged-in users will have their progress saved automatically.