How a bot can reduce pull request merges in the ASP.NET Core repo

Wednesday, May 29, 2019 0 Comments

When a contributor submits a pull request to a repository, this is a gift to an open source maintainer. But it can also contain a big challenge if there are merge conflicts.

A merge conflict indicates that the contributor changed files that others have changed in the main branch. When you attempt to merge two branches where people changed the same, Git attempts to merge those changes cleanly.

However, it’s not always possible for Git to reconcile those changes, resulting in merge conflicts. In those cases, it’s up to the maintainer to manually and painstakingly merge the changes. Or, as is often the case, they’ll ask the contributor to do it and push to the branch again. This is a lot of time-consuming tedious work.

mergedroid is a small GitHub app that connects to your repo and tries to automatically resolve merge conflicts in pull requests that GitHub can't. This saves tons of manual work. And it seems mergedroid can do a pretty good job, as the results in the ASP.NET Core repo show:

According to these results, almost 20% of the pull requests that required manual intervention, could have been automated by mergedroid.

Also, if you look at the file level, up to 45% of the files with merge conflicts could be automatically merged using a tool like gmaster Git GUI (this is not the job of mergedroid but its Git GUI evil twin. This is because the "bot" in mergedroid must solve the entire branch or nothing, even if just 1 of 99 files can't be automatically merged. When that happens, human interaction is required and then a good merge tool helps).

Do you want to deep inside how one of those merges that can be automated looks like? Keep reading.

A cross-file merge successfully automated by mergedroid

Let's go for a real case.

This was a merge that happened between these two commits:

Basically, as the comment of 13d9774e7afe5bcdc7ed9186e4815d5b3aed429c says:

Merge remote-tracking branch 'origin/release/2.1' into release/2.2

This was a manual merge. Here’s a visual representation of what happened...


  • src/theirs is the 2.1 branch.
  • dst/yours is the destination, the 2.2 branch.
  • base is the common ancestor of the two branches.

The method GetNextPort in TestUriHelper.cs was modified on the 2.1 branch . At the same time, the same method was also modified on the master branch, but also moved to a different file (TestPortHelper). Uh-oh! This results in a conflict that Git doesn’t know how to resolve.

Note: this actual diagram showing how the method was moved to a different class/file and modified in parallel is what the gmaster GUI shows when you run a merge.

Let’s take a closer look at the changes in each branch. This is the change that was done in the 2.1 branch:

This shows that the author deleted a comment inside of the method body and added a comment just before the method.

These are the changes made in parallel in master. Remember, the method was moved to a different file too:

It is exactly the same change, but applied to a different file since the method was moved.

Git doesn’t have semantic understanding of code, so it doesn’t realize that this change represents a method being moved with a comment change. It just sees the fact that the text here has conflicting changes and reports a merge conflict. The good news is mergedroid does understand code and can merge this automatically!

What else might have happened

In this case the method was modified in exactly the same way in both contributors. In practice, you often run into situations where:

  • The method was renamed after being moved to the new file.
  • And only one of the contributors modified the actual body.

mergedroid can still handle that situation with an automatic and correct merge.

How the GUI can help?

Well, suppose that both contributors moved the method to two different files. This is what we call a "divergent merge case". Even if mergedroid can't solve this because it needs human intervention, gmaster, the GUI that shares the same semantic technology, can help you detect and fix this type of conflict that bare Git can't, because it doesn't look for methods moved across files during merge as gmaster and its semantic merge tech do.

We develop gmaster, a Git GUI with semantic superpowers. It parses the code to really understand how it was refactored and then diff it and merge it as a human would do, matching methods instead of lines.

If you want to try it, download it from here.

We are also the developers of SemanticMerge and Plastic SCM, a full-featured version control.