4.1 Version Control Architecture: TFVC vs Git in F&O

Key Takeaways

  • Dynamics 365 Finance and Operations historically defaults to Team Foundation Version Control (TFVC) as a centralized repository with server-mapped workspaces, while Git provides a distributed repository model increasingly utilized in modern containerized development and the Unified Developer Experience (UDE).
  • Workspace mapping rules strictly mandate mapping the source control metadata directory ($/Project/Trunk/Main/Metadata) directly to the local PackagesLocalDirectory on the developer VM, while mapping the projects directory ($/Project/Trunk/Main/Projects) to the local Visual Studio projects folder.
  • Version control repositories in F&O track only declarative source assets: model descriptor XML files (Descriptor/ModelName.xml) and element XML files, while strictly excluding binary outputs, intermediate reflection metadata, and personal user settings.
  • Exclusion files (.tfignore for TFVC or .gitignore for Git) must explicitly ignore binary assemblies (bin/, *.dll, *.pdb), intermediate compilation artifacts (XppMetadata/), resource caches, and user-specific project files (*.rnrproj.user, *.csproj.user) to prevent repository corruption.
  • Enterprise check-in governance enforces linking commits to Azure Boards work items for traceability, establishing code review policies, and requiring automated gated check-in builds before code changes are committed to protected branches.
Last updated: September 2026

4.1 Version Control Architecture: TFVC vs Git in F&O

Quick Answer: Dynamics 365 Finance and Operations (F&O) supports two primary version control architectures: Team Foundation Version Control (TFVC) (a centralized system where developers map server folders directly to local disks) and Git (a distributed system where every developer possesses a complete local clone of the repository). For traditional Tier 1 Cloud-Hosted Environments (CHEs) and developer Virtual Machines (VMs), Microsoft's standard architecture relies on TFVC with a strict workspace mapping: the server folder $/Project/Trunk/Main/Metadata maps directly to the local application metadata folder (PackagesLocalDirectory, located on C:\AOSService\PackagesLocalDirectory or K:\AosService\PackagesLocalDirectory), while $/Project/Trunk/Main/Projects maps to the local Visual Studio solution path. Repositories must track only declarative XML source elements and Model Descriptor files ([ModelName]/Descriptor/[ModelName].xml). Binary outputs (bin/, *.dll, *.pdb), intermediate generated code (XppMetadata/), and personal user settings (*.rnrproj.user, .vs/) must be explicitly excluded via .tfignore or .gitignore.


1. Centralized TFVC vs. Distributed Git Architecture

Choosing and managing the version control system is a fundamental architectural decision in Dynamics 365 F&O implementations. While modern software engineering broadly embraces Git, Dynamics 365 F&O has deep architectural roots in TFVC, and both systems are heavily tested on the MB-500 exam.

Architectural Comparison: TFVC vs. Git

Architectural AttributeTeam Foundation Version Control (TFVC)Distributed Git Version Control
TopologyCentralized: A single centralized Azure DevOps server repository holds all revisions and branch histories.Distributed: Every developer maintains a full local clone containing the entire commit history and all branches.
Workspace ModelUses server-path or local-path workspace mappings that bind specific server paths directly to absolute local file system paths.Clones the entire repository into a root directory; developers switch branches locally without changing workspace mappings.
Metadata IntegrationDeep, native integration with the Visual Studio Application Explorer and Dynamics 365 menu tools.Fully supported in modern Visual Studio and Unified Developer Experience (UDE); requires local branch hygiene.
Branching & SwitchingHeavyweight: Branches exist as physical server directory trees (e.g., /Main, /Dev). Switching branches requires separate folder mappings.Lightweight: Branches are discrete 41-byte pointer references to commits. Switching branches swaps files in-place within the working tree.
File Locking & CheckoutSupports pessimistic locking (check-out locks preventing others from editing) and server workspaces.Strictly optimistic concurrency; no native file locking on standard repositories. All conflicts resolve post-commit at merge/pull.
Offline WorkLimited in server workspaces; local workspaces support offline edits but require server reconnection for check-in.Full offline capability: developers can commit, branch, view log history, and diff revisions completely offline.
Target EnvironmentTraditional Tier 1 Cloud-Hosted Environments (CHEs) and downloaded VHDs.Cloud-hosted VMs, local development, containerized builds, and Unified Developer Experience (UDE) in Power Platform.

TFVC Workspace Types: Local vs. Server Workspaces

When configuring a TFVC workspace on a development VM, developers must choose between two workspace modes:

  1. Local Workspaces (Recommended Default):
    • Visual Studio automatically detects file modifications, additions, and deletions outside the IDE using a client-side scanner.
    • Files on disk are not marked read-only.
    • Developers can edit code while disconnected from Azure DevOps; changes are queued and presented upon reconnecting.
    • Ideal for standard development where workspace size does not exceed tens of thousands of files.
  2. Server Workspaces:
    • All unedited files on disk have the Windows read-only attribute set.
    • Visual Studio explicitly removes the read-only attribute only when a file is checked out via an active network call to Azure DevOps.
    • Required when managing extremely massive repositories with hundreds of thousands of files where local scanning introduces disk I/O latency, or when teams mandate strict checkout locks to prevent concurrent modifications of binary resources.

2. Workspace Mapping Architecture & Rules

In Dynamics 365 F&O, the Application Object Server (AOS) runtime, the X++ compiler (xppc.exe), and the Visual Studio Application Explorer operate directly against a physical directory known as PackagesLocalDirectory. If files are checked out to an arbitrary folder on the dev machine, the F&O tooling cannot locate, build, or debug them.

The Golden Repository Structure

A standard Dynamics 365 F&O version control repository is organized into a clean folder hierarchy under a designated trunk or branch:

$/ContosoFinance/Trunk/Main/
├── Metadata/                  <-- Contains all custom models, extensions, and descriptor files
│   ├── ContosoSuite/          <-- Custom Package (Module)
│   │   ├── ContosoSuite/      <-- Custom Model within the Package
│   │   │   ├── AxClass/       <-- X++ source class XML files
│   │   │   ├── AxTable/       <-- Table definition XML files
│   │   │   ├── AxForm/        <-- Form definition XML files
│   │   │   └── Descriptor/    <-- Model descriptor file (AxModelInfo / ContosoSuite.xml)
│   └── ApplicationSuite/      <-- Extended Microsoft Package (Extensions only)
│       └── ContosoAppSuiteExt/ <-- Custom Model extending standard ApplicationSuite
└── Projects/                  <-- Contains Visual Studio Solution (.sln) and Project (.rnrproj) files
    ├── ContosoSuite.sln
    └── ContosoSuite/
        └── ContosoSuite.rnrproj

Strict Mapping Rules

To establish a working development environment, the developer must open the Source Control Explorer in Visual Studio and define exactly two distinct workspace folder mappings:

  1. Metadata Mapping (Absolute Requirement):
    • Server Path: $/ContosoFinance/Trunk/Main/Metadata
    • Local Path: C:\AOSService\PackagesLocalDirectory (or K:\AosService\PackagesLocalDirectory depending on the VM drive configuration)
    • Why? When you invoke Get Latest Version, Azure DevOps downloads the custom model packages directly into the active AOS package folder. Visual Studio immediately recognizes the models, displays them in Application Explorer, and compiles them into the runtime environment.
  2. Projects Mapping:
    • Server Path: $/ContosoFinance/Trunk/Main/Projects
    • Local Path: C:\Users\Administrator\Documents\Visual Studio 2019\Projects (or C:\Dynamics365\Projects)
    • Why? Visual Studio solutions (.sln) and Finance and Operations projects (.rnrproj) must never be mapped inside PackagesLocalDirectory. Storing project files inside the metadata folder causes compiler errors, clutters model folders, and violates package isolation boundaries.

[!IMPORTANT] Critical Mapping Rule: Never map the root folder $/ContosoFinance/Trunk/Main directly to PackagesLocalDirectory. Doing so forces the Projects/ folder and root configuration files to reside inside the AOS package store, which corrupts package discovery and triggers severe compilation diagnostics.


3. Tracking Metadata: Model Descriptors vs. Element XML Files

Dynamics 365 F&O is an entirely declarative, metadata-driven architecture. Every element—whether a table, class, data entity, or form extension—is stored as an individual, human-readable XML file on disk. Version control must track these source XML files while respecting the distinction between packages, models, and descriptors.

Packages vs. Models on Disk

  • Package (Module): An independent deployment and compilation unit. A package compiles into a single .NET assembly (.dll). Examples include ApplicationPlatform, ApplicationSuite, or a custom package like ContosoCustomizations.
  • Model: A design-time subdivision of a package. A package can contain one or multiple models. Each model contains its own elements and business logic, but all models inside a single package compile together into that package's single assembly DLL.

Model Descriptor Files

Every model within a package must have a corresponding Model Descriptor file located inside the Descriptor directory: PackagesLocalDirectory\<PackageName>\<ModelName>\Descriptor\<ModelName>.xml.

The model descriptor XML contains critical configuration attributes:

  • Model Name and Display Name: Unique identifier of the model.
  • Publisher: Authoring organization (e.g., Contoso Corp or ISV Partner).
  • Layer: Application layer (e.g., isv, var, cus, usr).
  • Version: Three-part semantic version string (e.g., 1.0.0.0).
  • Module References (Dependencies): The list of other packages that this model depends on (e.g., ApplicationFoundation, ApplicationSuite, Directory).
<?xml version="1.0" encoding="utf-8"?>
<AxModelInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Name>ContosoSuite</Name>
  <Publisher>Contoso Enterprises</Publisher>
  <VersionMajor>1</VersionMajor>
  <VersionMinor>0</VersionMinor>
  <VersionBuild>0</VersionBuild>
  <VersionRevision>0</VersionRevision>
  <Layer>cus</Layer>
  <ModuleReferences>
    <string>ApplicationFoundation</string>
    <string>ApplicationPlatform</string>
    <string>ApplicationSuite</string>
  </ModuleReferences>
</AxModelInfo>

[!WARNING] The Missing Descriptor Trap: If a developer creates a new model in Visual Studio and checks in the element files (such as tables and classes) but forgets to check in the Descriptor/<ModelName>.xml file, other developers who get latest will encounter severe compiler errors. Their Visual Studio Application Explorer will not recognize the folder as an active model, and the automated build pipeline will fail with missing assembly reference errors.


4. Exclusion Rules: .tfignore and .gitignore Architecture

A critical responsibility of the F&O developer is ensuring that transient, intermediate, and compiled binary files are never committed to version control. Checking in compiled binaries or user-specific files bloats the repository, causes merge collisions, locks files during team builds, and breaks continuous integration pipelines.

Files and Folders That MUST Be Excluded

  1. Compiled Binary Outputs (bin/, *.dll, *.pdb, *.winmd):
    • Each package contains a bin/ directory where the compiler outputs compiled .NET assemblies and debugging symbol files (.pdb).
    • These must be generated purely from source by the local build or the Azure DevOps CI pipeline.
  2. Intermediate Reflection and Cross-Reference Data (XppMetadata/, XppIL/):
    • The compiler generates XppMetadata/ to hold intermediate parsing trees and reflection indices used during compilation and debugging.
    • These files change on every compile and must never be committed.
  3. User Project and IDE Cache Settings (*.rnrproj.user, .vs/, *.suo):
    • User files contain personal developer preferences, such as the active company (DAT, USMF), the startup project, startup element, and window layouts.
    • Committing these files overwrites personal settings across the entire development team.
  4. Standard Microsoft Package Folders:
    • Standard packages (ApplicationPlatform, ApplicationSuite, etc.) must never be checked into version control. Only custom packages or custom extension models extending standard packages may be tracked.

Complete .tfignore Specification

A .tfignore file must be placed in the root of the workspace mapping (e.g., at $/ContosoFinance/Trunk/Main/Metadata/.tfignore and $/ContosoFinance/Trunk/Main/Projects/.tfignore):

# ========================================================
# TFVC Ignore Rules for Dynamics 365 Finance and Operations
# ========================================================

# Ignore compiled binaries and debug symbols
\bin\
*.dll
*.pdb
*.ilk
*.winmd

# Ignore intermediate compiler and reflection metadata
\XppMetadata\
\XppIL\

# Ignore temporary resource caches and output directories
\Resources\
\Output\
\obj\

# Ignore Visual Studio user preferences and solution caches
*.rnrproj.user
*.csproj.user
*.vbproj.user
*.suo
*.user
.vs\

# Ignore build runbooks and local test results
TestResults\
*.runbook.xml
*.runbook

For Git-based implementations (such as Unified Developer Experience workspaces), the identical file and directory patterns are placed into a root .gitignore file.


5. Check-in Policies, Work Item Association & Governance

Enterprise Dynamics 365 development mandates strict check-in governance configured within Azure DevOps Team Project settings.

Mandatory Work Item Association

Check-in policies can be configured in TFVC to block any check-in that does not link to an active Azure Boards Work Item (such as a User Story, Bug, or Task). This ensures complete traceability: any code line changed in an X++ class or table extension can be traced directly to a business requirement, functional design document (FDD), or defect ticket.

Check-in Discipline: Atomic Commits

Developers must practice atomic check-ins:

  • Atomic Scope: All related elements for a feature—including the model descriptor (if newly created or updated), table extensions, classes, form extensions, and label files—must be checked in together within a single changeset or Git commit.
  • Partial Check-in Anti-Pattern: Checking in an X++ class that references a new table field before that table field's XML file is checked in breaks the build for every other developer on the team.

6. Scenario Walk-Through: Onboarding a New Developer VM

Scenario: Setting Up Contoso's Developer Workspace

David, a new senior X++ developer, is assigned a fresh Tier 1 developer VM deployed via LCS. He needs to connect his machine to Contoso's Azure DevOps repository and prepare his environment for active feature development without corrupting standard models.

Step-by-Step Implementation:

  1. Open Visual Studio as Administrator: David launches Visual Studio with elevated administrative privileges (mandatory for interacting with IIS worker processes and PackagesLocalDirectory).
  2. Connect to Azure DevOps: Under Team > Manage Connections, David connects to the https://dev.azure.com/ContosoFinance organization and selects the ERP-Customizations team project.
  3. Configure Workspace Mappings: In Source Control Explorer, David opens the Workspace dropdown and selects Workspaces > Add:
    • He sets the workspace type to Local.
    • Mapping 1 (Metadata): Sets Server Path to $/ERP-Customizations/Trunk/Main/Metadata and Local Path to K:\AosService\PackagesLocalDirectory.
    • Mapping 2 (Projects): Sets Server Path to $/ERP-Customizations/Trunk/Main/Projects and Local Path to C:\Dynamics365\Projects.
  4. Verify .tfignore Presence: David verifies that K:\AosService\PackagesLocalDirectory\.tfignore exists and contains exclusions for bin\, XppMetadata\, and *.rnrproj.user.
  5. Perform Get Latest: David right-clicks the $/ERP-Customizations/Trunk/Main root in Source Control Explorer and clicks Get Latest Version (Recursive).
  6. Execute Full Build & DB Sync: Once downloaded, David opens Visual Studio, navigates to Extensions > Dynamics 365 > Build models..., selects the ContosoSuite model, checks Synchronize database, and initiates the build. The build succeeds, creating local bin/ assemblies and synchronizing tables to local SQL Server without any version control pending changes generated for binary artifacts.

7. Real-World Exam Traps: Version Control in F&O

[!WARNING] Exam Trap 1: Checking In the bin/ or XppMetadata/ Directories Questions frequently ask which directories must be committed when creating a new model. Exam options that include bin, XppMetadata, or *.rnrproj.user are strictly incorrect. Only source XML files and the Descriptor/<ModelName>.xml file should be committed.

[!WARNING] Exam Trap 2: Root Mapping $/Trunk/Main Directly to PackagesLocalDirectory A common question tests workspace mapping paths. Mapping the root branch $/Project/Trunk/Main directly to PackagesLocalDirectory puts the Projects directory inside the AOS package store, violating model architecture and causing compiler errors. The Metadata subfolder must be mapped to PackagesLocalDirectory, while Projects must map to a separate directory.

[!WARNING] Exam Trap 3: Omitting the Model Descriptor XML A scenario describes a developer who created a new model with several tables and classes, checked them in, and went on leave. Other developers report that they cannot see the new model in Visual Studio Application Explorer despite getting latest. The root cause is that the author failed to check in the Model Descriptor file (Descriptor/<ModelName>.xml).

[!WARNING] Exam Trap 4: Tracking Standard Microsoft Platform Packages The exam may present an option recommending to check in the entire PackagesLocalDirectory folder. This is a severe architectural error. Standard packages (ApplicationSuite, ApplicationPlatform) are multi-gigabyte binaries provided by Microsoft; checking them into source control corrupts versioning and will immediately overwhelm repository storage limits.

Loading diagram...
Dynamics 365 F&O Source Control Workspace Mapping Architecture
Test Your Knowledge

When configuring a Team Foundation Version Control (TFVC) workspace on a Dynamics 365 Finance and Operations developer VM, what is the required local mapping destination for the repository Metadata folder ($/Project/Trunk/Main/Metadata)?

A
B
C
D
Test Your Knowledge

Which set of files and directories must be explicitly excluded from version control tracking via .tfignore or .gitignore in a Dynamics 365 Finance and Operations development environment?

A
B
C
D
Test Your Knowledge

A developer creates a new custom model in Visual Studio, adds several tables and classes, and checks in the changes. When other developers perform a Get Latest operation, they report that the new model does not appear in Visual Studio Application Explorer and their projects fail to compile. What is the most likely cause of this issue?

A
B
C
D
Test Your Knowledge

How do Local Workspaces differ from Server Workspaces when utilizing Team Foundation Version Control (TFVC) in Visual Studio for Dynamics 365 Finance and Operations development?

A
B
C
D