Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
Full Version Control entry
How-to guide

Adopting Version Control on a Salesforce project

Adopting Version Control on a Salesforce project is a sequence of decisions that compound: pick a Git provider, set up a Salesforce DX project, decide on a branching strategy, retrieve existing metadata into source, build a baseline CI pipeline, and grow the pipeline over time. The full setup takes a few weeks of focused work, but each step delivers value on its own. Most teams that fail to adopt Version Control stall at the metadata retrieve step because the Profile XML diffs are too painful to manage; pre-plan for that.

By Dipojjal Chakrabarti · Founder & Editor, Salesforce DictionaryLast updated May 19, 2026

Adopting Version Control on a Salesforce project is a sequence of decisions that compound: pick a Git provider, set up a Salesforce DX project, decide on a branching strategy, retrieve existing metadata into source, build a baseline CI pipeline, and grow the pipeline over time. The full setup takes a few weeks of focused work, but each step delivers value on its own. Most teams that fail to adopt Version Control stall at the metadata retrieve step because the Profile XML diffs are too painful to manage; pre-plan for that.

  1. Set up the Git repository and the Salesforce DX project

    Create a private Git repo on GitHub, GitLab, or Bitbucket. Initialize a Salesforce DX project with sfdx force:project:create or the modern sf project generate command. The project structure includes a manifest folder for package.xml files, a config folder for scratch org definitions, and a force-app folder for metadata. Commit the initial project structure. Add a .gitignore that excludes the .sfdx folder (local-only state) and any local environment files. Document the repository conventions in a CONTRIBUTING.md so future joiners know the structure.

  2. Retrieve existing metadata from the org into source

    From the project root, authorize the source org (production or the most-current sandbox) with the Salesforce CLI. Run a metadata retrieve to pull every relevant metadata type into the force-app folder. This is where the Profile XML problem surfaces; expect very large, hard-to-diff files. Run a cleanup pass that removes Profile entries you do not control (managed package object references, for example) using Sfpowerkit or a custom script. Commit the cleaned baseline to a long-lived branch (typically main or master). This baseline is the starting point for all future work.

  3. Adopt a branching strategy and write it down

    Pick GitFlow, trunk-based, or a hybrid based on your release cadence. Document the strategy in the repo CONTRIBUTING.md or in a separate ARCHITECTURE.md. Specify which branch maps to which environment (main maps to production, develop maps to integration sandbox, feature branches map to per-developer scratch orgs). Configure branch protection rules: main requires PR approval and passing CI checks before merge, develop allows direct push with passing checks. Train the team on the workflow with a hands-on session, not just a written doc.

  4. Build the initial CI pipeline

    Set up a CI workflow that runs on every PR and every push to main. The workflow authorizes the relevant Salesforce org using a stored credential or JWT key, runs sf project deploy validate against the target sandbox, runs Apex tests with sf apex run test, and reports results back to the PR. Start with validation-only (deploy without committing) for PRs and full deploy for merges to main. Grow the pipeline over time to include data deployments, integration tests, and post-deploy verification. Document each pipeline stage and the credentials it needs in the repo README so future maintainers can update it.

Gotchas
  • Profile XML diffs are notoriously unreadable. Use Permission Sets and Permission Set Groups for everything you can, and use tools like Sfpowerkit to clean Profile XML on retrieve.
  • Salesforce DX source format and Metadata API format are different. Retrieving in the wrong format causes diff noise and merge conflicts. Stick to DX source format for the project.
  • Scratch Orgs expire automatically (7 days default, 30 days max). Work that has not been pushed to source by expiration is lost. Push to Git as a daily habit, not at end-of-feature.
  • CI deploys count against the daily API request limit on the target org. Run tests against scratch orgs or dedicated CI sandboxes; do not run them against production.
  • Branch protection rules can be bypassed by anyone with admin rights to the repo. Use the bypass sparingly and audit it. Breaking the rule one time creates a culture problem.

See the full Version Control entry

Version Control includes the definition, worked example, deep dive, related terms, and a quiz.