← All articles
TMDLFabric

Putting TMDL Under Source Control

A semantic model saved as a single .bim JSON file is technically "in Git," but nobody is reviewing a 4,000-line JSON diff in a pull request. TMDL (Tabular Model Definition Language) exists specifically to fix that: it's a folder-per-table, file-per-object format designed to be read and diffed by humans, not just tools.

The layout that makes diffs readable

definition/
  database.tmdl
  model.tmdl
  tables/
    Sales.tmdl
    Date.tmdl
    Product.tmdl
  relationships.tmdl
  cultures/
    en-US.tmdl

One table, one file. When a teammate adds a measure to Sales, the pull request touches tables/Sales.tmdl and nothing else — no more "why did the entire model file change because of one DAX edit."

A measure, as TMDL actually writes it

measure 'Total Sales' = SUMX ( Sales, Sales[Quantity] * Sales[Unit Price] )
    formatString: $#,##0.00
    displayFolder: Financials

That's the whole diff for adding a measure. Compare that to the equivalent change in a .bim file, where the same edit is buried inside a nested JSON array and Git's line-based diff can't tell you anything useful about what changed.

Getting there from Power BI Desktop

Enable the Power BI Desktop developer mode / PBIP (Power BI Project) format, which saves the report as a folder including a .SemanticModel directory — that's where the TMDL definition lives. Point Git at the project root, and treat the .SemanticModel folder like application source code: branch it, review it, and let CI validate it before it reaches production.