This article explores why you'll often see metadata differences between a freshly updated source control repository and its parent org.
The scenario
You’ve created a new git repository and want to seed it with metadata from your production org as a first step in introducing source driven development in your team.
In Gearset, you run a comparison using the Compare all
metadata filter, from production as the source, to the master branch of your repository as the target. As expected, all the items show up as new - this is a blank repo after all. You select all items to deploy. Once the deployment completes, you check git and see all your metadata is now in the repository. To check that everything is in sync, you run a second comparison from master to production, with the expectation that every component will be listed as No difference
. To your surprise, there are a number of items showing up as being different already, and when you look at the XML there are highlighted differences. How can this be, since this repository was just updated from that production org? Shouldn’t they be totally in sync?
Orgs are moving targets
Salesforce orgs are constantly changing environments, and their metadata is rarely static:
Automated jobs run behind the scenes, platform upgrades are applied, and third party apps and packages regularly make configuration changes.
Developers and admins make manual changes, adding new fields, changing profile settings, and altering layouts.
End users generate new reports, upload images and static resources, and create email templates to work with.
By contrast, git repositories are entirely static. No files will be changed in a git repository without direct interaction, and each change will be tracked (and usually peer reviewed) before it ends up in the master branch. The pace of change between these two environments is stark.
Drift happens rapidly
When you deploy metadata from an org into a repository, you’re deploying a snapshot of the org at that point in time. The repository will leave that snapshot unchanged, while the org will continue to evolve from that point onwards. This is the opposite to most other development platforms where the source code in the repository is what defines the end application. With Salesforce, the org is the living app and the extracted metadata is simply a snapshot.
As a result, even a mature source driven workflow will see many changes being made directly in Salesforce. Automated jobs like the clean data service will continually trawl through the org. Managed packages may be customized or installed. End users will make the occasional change in the org. And once every few months, Salesforce platform updates will be rolled out. This means differences will start to appear between an org and its repository almost immediately after they have been synchronized.
To add to these “true” changes, there are a number of metadata types which just don’t work well with source control and can produce false positives. The ordering of some metadata component types, such as layouts, is often randomized by the metadata API each time they are downloaded. While this doesn’t have a functional impact in the org, as far as git and Gearset are concerned an ordering change is a change to the XML, and so it will be flagged as different. Other component types, such as Site.com, are stored as binary blobs and so prevent inspection of the raw XML. Any changes to any part of this community site will result in a new MD5 hash, thus causing it to appear as a difference between the org and git.
Probably the most common example of this metadata showing inconsistent behavior between Salesforce and source control is profiles. The subcomponents returned by Salesforce for a profile depend on the other metadata types in the retrieval request over the metadata API. For example, if you select just the Profile
metadata type in your custom metadata filter and run a comparison, you'll get no results in the comparison results. In git, if you include the Profile
metadata type, you'll always get all parts of the profile returned. To demonstrate this, run a comparison between a Salesforce org and a git repository that are in sync using only the Profile
metadata type in your filter. It will appear that most of the profile items have been deleted from Salesforce! If you tried to deploy this, the deletions would either be pushed into your repository, or attempted to be deleted from your org likely causing deployment failures, depending on the source/target combination. Now, run another comparison between the same two environments using Gearset's Default profiles and permission sets comparison
filter, which includes all the related profile metadata types. Suddenly Salesforce and git are back in sync.
So how do you spot the genuine changes from the noise when you’re working with Salesforce and source control?
Filtering out the noise
The first step is to reduce the amount of metadata that you’re storing in git. It’s a common (and understandable) misconception that all metadata types should be stored in your repository. While in theory that would make git the closest representation of your org possible, it doesn’t work in practice. The noise generated by certain metadata types can make it extremely difficult to narrow in on the important changes.
Instead of attempting to track everything in git, focus on the metadata you’re modifying most frequently, and that has the greatest impact on the configuration of your org. Things like your Apex
, Custom objects
, Lightning web components
, Profiles
, Permission sets
, Standard value sets
and Global value sets
. Start with a subset of metadata. Once you’ve got a solid release pipeline and you’re comfortable with git and Gearset, start adding more components one at a time. You’ll quickly spot which types cause the greatest headaches with git.
The second step is to use custom metadata filters in Gearset to focus on the metadata you’re most actively working on and most interested in deploying between your orgs and git. If a current sprint is focusing on adding Lightning web components
, you may want to narrow down the default comparison filter to something more targeted (but don't forget the requisite profiles!). This will not only reduce the noise in your comparisons, but also speed up the comparison and deployment process.
By reducing the number of metadata types in git, understanding how git and Salesforce differ, and using filters to focus your comparisons, you’ll find git a much more effective tool in your CI/CD process.
Common reasons for differences
Here are some possibilities to look out for in trying to understand why there are still differences.
Installed packages
If you selected the Installed package
metadata type in the comparison filter, and your target git branch is empty, Gearset will not show managed package metadata items for you to deploy. You will need to run a second comparison to surface the managed package metadata items after the package versions in the environments are the same. This is documented in detail here.
XML re-order
The difference can be due to an XML reorder issue where the Salesforce API is returning re-ordered XML tags. This issue is discussed in detail here.
Problem analyzers
The Gearset problem analyzers may be excluding metadata from your deployment. Make sure you are deselecting the suggestions to remove metadata items in this stage.