How to avoid and resolve merge conflicts in your Salesforce CI/CD pipeline

How to avoid and resolve merge conflicts in your Salesforce CI/CD pipeline

Holly White on

Share with

LinkedIn
Twitter

For teams using version control, merge conflicts are just a fact of life. They can never be entirely avoided when you have developers working on shared projects.

If teams haven’t found an effective way to work with version control, or they’re new to Git, merge conflicts often become a big point of frustration. But small changes to the way your team works can dramatically reduce the likelihood of merge conflicts, and significantly reduce their complexity when they happen.

What is a merge conflict?

Merge conflicts happen when two different Git branches, that have both had changes made to the same files, are merged back into a common branch.

These are usually changes made on the same or adjacent lines, and require human intervention to decide what the resulting change should look like. So, Git knows there’s an issue, doesn’t know how to deal with it, and will ask you how to proceed to prevent something being overwritten.

The two main conflicts that you’re likely to encounter are either content conflicts or path related conflicts. Content conflicts are changes in the files themselves and path conflicts are caused by files being renamed or deleted.

Illustration of unresolved merge conflict

What causes merge conflicts for Salesforce teams?

Long-lived branches

The longer you leave a branch open, the more likely it is that a teammate will begin working on the same files as you. You could be stepping on each other’s toes without realizing, which will cause conflicts when you try to merge back into your common branch.

Salesforce’s representation of metadata

There are a few ways in which the on-disk representation of Salesforce metadata isn’t ideal:

  1. Salesforce metadata is represented as XML, and Git’s diff is known to be bad at comparing changes in XML files.

  2. Metadata is often returned in a non-deterministic order by Salesforce’s Metadata API. This means the ordering of elements within an XML file returned by the API can vary from request to request without any underlying semantic difference. As a result, you may hit all sorts of conflicts where you might not have expected any.

  3. Salesforce uses very large files to represent certain metadata types containing many configurable elements. Profiles are a great (or infuriating) example where changing the permissions for two unrelated objects can result in adjacent changes in a Profile giving rise to merge conflicts.

10 best practices to avoid merge conflicts

1. Keep your environments in sync

It’s really easy for your environments to slip out-of-sync; a few hotfixes in production and some abandoned projects can be the beginning of a much bigger problem later on. After a while, the drift could be so big that it feels like environments will never be in sync again.

Sandbox refreshes aren’t always an option and come with their own limitations. The best way to get your orgs in sync is to back promote from production down to the lower environments. This helps to reduce merge conflicts by maintaining consistent changes across all environments​​.

2. Avoid teammates overlapping on the same parts of an org

It’s a good idea to avoid having multiple developers working on the same areas of the codebase at the same time. Merge conflicts only happen when multiple developers change to the same file.

But avoiding this can be really difficult for those larger types, such as Lightning Pages and Layouts. Profiles are notorious for breeding merge conflicts because they contain entries for lots of different parts of your org; just take a look at the API docs to see how many subtypes there are. Since Profiles contain entries for the majority of your org, and because they’re stored as large, single files, two developers making changes to independent parts of an org may end up touching the same Profiles. Hello merge conflict!

3. Use a tool with automated conflict detection

Some tools use semantic conflict detection. This means that when you come up against a conflict, your tool will be able to understand what changes you’re actually trying to make and resolve the conflict automatically. For example, imagine you have two developers adding a custom label to the same line of code. Instead of hitting a conflict because the same line of code has been changed, semantic merge analysis will know that two developers want two different labels. It will then add them as two new labels, one above the other.

4. Choose a relevant branching strategy

Choosing the right branching strategy for your team is an important step in your DevOps adoption. No strategy eliminates merge conflicts, but the well-established strategies have can help in different ways.

A simpler strategies, like feature branching, involves peeling away from main and then merging changes back in. Unless feature branches are kept open for long periods, the simplicity of this model can help you avoid too many merge conflicts.

Other strategies, like GitFlow, delay merging changes into the main branch until the end of a sprint. Normally, delaying a merge would increase the risk of merge conflicts. But the good thing about GitFlow is that everyone is creating features from the develop branch, dealing with conflicts as they go. As long as the develop and main branch are kept in sync, merging into main shouldn’t see many conflicts.

5. Merge your branches early

Merging as soon as possible keeps your branches small and short-lived. This means your main branch won’t have changed that much — fewer changes will have been added and merged since you made your change, reducing the likelihood of merge conflicts in the first place. It also helps that you’re closer to the point when you did the work, and will more likely have the context of the changes you were making.

Compare the two diagrams below to see how merging late creates more merge conflicts.

Merging Salesforce changes late
Merging Salesforce changes early

6. Merge your branches often

If you’re going to hit a conflict, you’d rather it was in one of ten small PRs, than in one big PR at the end. That way, it’s easier to resolve the conflict when it does arise, because the PR is more focused. And your rate of success for merging is much higher, which means you can keep work moving through the pipeline.

There are some long-running projects that are easiest to keep apart from the BAU pipeline. Gearset supports long-term projects, so you can do that while syncing from the main pipeline to the project.

7. Have one feature (or less) per PR

It’s best to keep all changes for a feature to a single feature branch — or many single feature branches. We know that features can become much bigger projects so creating PRs in slices is actually a better method, and allows you to merge often and earlier.

What you’ll want to avoid is resisting the temptation to add a change from another project onto your feature PR. This will cause complications if you want to revert the PR at a later date or if a teammate is trying to find a specific change and it’s in a completely different PR altogether.

8. Encourage teammates to take ownership of their merges

Encouraging team members to merge their own work will create less bottlenecks in your release process. The reason for this is simple: developers are much more familiar with their own work and are much better placed to make decisions on how to resolve Salesforce merge conflicts.

Using pull requests reviewed by another team member is fundamental to a healthy development process. But until that change is merged, it should be the responsibility of the original author to make sure that feedback is responded to and the change is ready for release.

9. Use delta CI deployments

Delta CI deployments only deploy the latest changes that have been made. These “little and often” commits make overwriting other developer’s work less likely and help you miss conflicts that might have happened if you bundle changes together in one deployment. Delta CI jobs are a great choice for teams who are just starting out on their DevOps journey and who are gradually starting to build up the metadata in version control.

10. Reduce file sizes

Remember that merge conflicts arise as a result of team members making changes to the same file. A good way to avoid this happening is to use smaller files, and more of them. There aren’t many places you have control over the composition of the source for your org. But where you do, you should take advantage of it.

Apex classes are a great example. By using smaller files, one for each unit of code, you’ll also be following good software engineering practice. The single responsibility principle (SRP), one of the SOLID principles for writing maintainable code, states that each unit in your codebase should be responsible for a single piece of functionality.

How to resolve Salesforce merge conflicts with Gearset’s Pipelines

You can’t banish all merge conflicts forever, but what you can do is try to limit their frequency and remove the pain whenever they crop up.

Gearset’s Pipelines gives your team complete visibility of all changes that are happening in your release pipeline, how much work there is waiting to be pushed, and provides you with the tooling to get these changes promoted through your environments quickly and successfully, without ever leaving Gearset. But how can Pipelines help with merge conflicts?

Gearset’s Pipelines shows you a visulization of all your environments.

Standard merge conflict resolution

Rather than rely on Git to merge changes and suffer the resulting conflicts, we’ve implemented a metadata-aware semantic merge algorithm, designed to dramatically reduce the frequency of merge conflicts in Salesforce metadata.

For example, if two developers on two different Git branches both add a new Custom Field, they might easily end up with new permissions in a Profile, on the same line of that Profile. Whoever merges their branch first will “win” the line, and the other person will need to edit the XML manually, or decide to take one side of the conflict.

Gearset’s semantic merge will know that each of the field permissions is actually for a different object — so it knows to put them each on a new line, in any order. Headache avoided, and you’re free to continue deploying happily.

Dedicated conflict resolution UI

There are some cases where even Gearset won’t be able to make the decision for you, for example if two developers change the name of a label. It’s not possible to include both so someone needs to choose which one to move forward with. We’ve made it as easy as possible to do this right in the Gearset UI. Just click on the merge conflict when Pipelines flags it, and decide which changes to accept.

Gearset’s Pipelines flags any merge conflicts so you can resolve them quickly, without leaving the UI.

Precision conflict resolution in Gearset

Merge conflict resolution in Salesforce isn’t always as easy as one conflicting change that’s easy to fix. That’s where Gearset’s precision conflict resolution comes in.

Instead of choosing one entire version of the conflicted file, Pipelines allows you to be more selective by choosing specific parts of two branches to take forward. This creates a new file combining the best parts of each branch and resolves any conflicts.

Gearset’s Pipelines allows you to pick the changes you want from two different branches.

Conflict resolutions are remembered

Merge conflicts become even easier to manage once you’ve decided how to rectify them in Pipelines. Gearset will store the conflict resolution you’ve chosen and give you the option of using the same fix when it comes up again in a later environment. This helps keep your environments in sync by using the same resolution across all of your orgs and takes the pain out of fixing the same conflict again and again.

Pipelines will rememeber your chosen resolution and give you the option to use it in a later environment.

Resolve merge conflicts for good

DevOps is fundamental to any high-performing Salesforce team. But having a stalled release pipeline and an overworked release manager frantically working through a big list of merge conflicts can erode a team’s faith in the process, leading teams to fall back on their former “easier” practices.

Adopting source-driven development means much more than injecting Git into your existing process. The highest performing teams actively go out of their way to avoid merge conflicts altogether following the 10 steps above, and let Gearset do the hard work whenever merge conflicts do crop up.

You can start using Gearset today to take full advantage of Pipelines, get a clear overview of your orgs and spend less time resolving conflicts. If you’d like to learn more about merge conflicts, and how you can implement a version control system into your business, then download our free CI/CD ebook.

Try all of Gearset for free