We Automated Resolving Merge Conflicts, and Here’s How | by Abhishek KM | May, 2022

Photo by David Ballew on Unsplash

In the world of Open-source, maintaining or contributing to an active repository is not exactly as straightforward as it seems and a merge conflict is something everybody has to deal with but nobody likes it. B̶u̶t at Felvin, w̶e̶ ̶l̶o̶v̶e̶ ̶m̶e̶r̶g̶e̶ ̶c̶o̶n̶f̶l̶i̶c̶t̶s it wasn’t much different.

This post will walk you through the following:

  • Felvin and Instant Apps
  • Structure of Instant Apps
  • Creating an Instant App
  • Merge Conflicts We Face
  • Automating and Resolving Merge Conflicts

Felvin, a radically powerful way for people to find information, achieved by converting everything you see on search engines into a plugin.

To know more about Felvin and how Felvin works, click here.

Instant apps are the small interactive cards that you get for your search queries. We can build instant apps for all kinds of use cases like dictionaries, checking football scores, stock prices or notes from your notion or even search history from company slack or anything! Click here to know more!

As the name suggests, instant-apps is a collection of apps created with the help of the open-source community and a sandbox to test those apps, all in one repository.

We achieve this by creating individual react apps and then exporting all the apps to a single react app as node modules.

Below is the folder structure of the repo. The apps created by the community are under apps/ eg: app1 and app2.
Each of those apps have their own package.json , App.jsx and index.ts .

folder structure of instant apps

packages/apps has all the apps imported and then helps export it to the sandbox.



And finally the yarn.lock file looks something like:

Now that we have a basic understanding of the structure, let’s look at how a new instant app is created and how that affects the repo.

A new instant app can be created by running yarn create-app .

Creating a new app will generate the following:

1* HmL9
folder structure of a new app (app1)

And update ./packages/apps/src/index.ts , ./packages/apps/package.json and ./yarn.lock

From creating a new app, we know that a few files (3 to be precise) are updated and these are usually the culprits behind the merge conflicts.

Let’s take a look at an example to understand this better.

The diagram below shows how we usually run into merge conflicts.

1*AaMODTb gocgZe9ZiwsBlg
Gitflow Diagram

We create a new branch and start working on App2 v1.0.0 right after App1 v1.0.0 is released. While we’re working on App2, there has been a new version of App1, which is v1.0.1.

Someone else creates a new branch for App3 v1.0.0 from the point App1 v1.0.1 was released and they manage to finish their app before we do. So, their branch is merged into the master branch before ours.

When we’re finally done with App2 v1.0.0 and are ready to merge into the master branch, we’d face the following merge conflicts and there’s a pattern to it:

1. /packages/apps/src/index.ts

In the index.ts file, the conflict isn’t that complex. It can be solved by accepting both the current and incoming changes but would require us to use regex or a text editor to resolve this.

2. packages/apps/package.json

In the case of package.json , things are quite different. It’s a bit more complex as there are versions of the app involved. Git does have options to accept incoming ( — theirs) and current ( — ours) changes based on files but is of no use to us.

3. yarn.lock

Similar to package.json , yarn.lock also has versions of the app that are conflicting but, if package.json has been resolved, just running yarn or yarn install would fix the conflicts.

At this point, we could rebase and then try merging it but rebasing is a bad idea. You can read why it’s a bad idea here.

…you can be certain that a true history will be more useful than a rewritten (or fake) one.

-Fredrik V. Mørken

To automate the process of merging and resolving conflicts, we chose to use a combination of python and shell. The inbuilt python libraries like glob, os and json were more than sufficient. We also used boilerplate code from ./packages/apps/src/index.ts and ./packages/apps/package.json as constants.

To solve the merge conflicts, the best way here is to generate ./packages/apps/src/index.ts and ./packages/apps/package.json from scratch by iterating over all the apps in the repository and getting the name and version of those apps. We wrote a class to do the very same. First, we initialize a bunch of stuff related to getting the path of each app and it’s package.json , ./packages/apps/src/index.ts and ./packages/apps/package.json .

Then we iterate over each app’s package.json to get the name and version.
To make it easy to follow, from here on, comments will be provided to better indicate what happens at each step.

1. Resolving ‘./packages/apps/src/index.ts'

2. Resolving ‘./packages/apps/package.json'

3. Resolving ‘yarn.lock'

As discussed previously, generating yarn.lock only requires us to run yarn or yarn install right after we resolve the other two files. For this, we:

a) First, get the name of the current branch
b) Then run git merge master which will stop before merging as there will be conflicts.
c) Run yarn or yarn install
d) Stage all the files
e) Complete the merge with the default merge message, we could also continue the merge with --continue flag but that’d require us to change the merge logs and edit it through vim.

You can have a look at the actual code here.

Merge conflicts could be a pain sometimes, but if you find repeating patterns with the conflicts, you probably can tame it, or make it your buddy by automating it. This post is not meant to help the masses but is meant to log my experience or maybe even spark ideas for someone who’s facing anything remotely similar because when we were trying to figure out a way to solve our merge conflicts, we couldn’t find much. The only question you need to ask yourself is — “is there a pattern to our merge conflicts?”

Special thanks to Harsh Gupta for pushing me to write this blog


News Credit

%d bloggers like this: