You should be doing 3-way merges

Damon Lundin
5 min readDec 7, 2017

--

I’ve come across quite a few developers who have been relying on 2-way merges to address merge conflicts when delivering code. This is because most interactive tools that come with our source control systems only support 2-way merges. But if you’re relying on 2-way merges, you’re doing it wrong.

To start, let’s be clear on when merges are required. This happens when two people make changes to the same file at the same time and then those changes need to be reconciled back into a single file. Often those changes occur in separate parts of the files that have no impact on each other. Most source control system can handle these types of merges automatically and they do it using an internal 3-way merge. But occasionally the changes conflict and a person needs to resolve the conflict manually.

Let’s start with an example file we wish to change.

<SomeFile.txt>
Sydney
London
New York

Now imagine someone removes “London” from this file (let’s call it file “(1)”) and at the same time someone else adds “Tokyo” to it (let’s call it file “(2)”). We would end up with these two files:

<SomeFile(1).txt>
Sydney
New York
<SomeFile(2).txt>
Sydney
London
New York
Tokyo

Now we want to merge these two files back into a common file. If you had no context about the changes made and all you had are the two resulting files, it would be impossible to do the merge correctly. At first glance, it might look like the second person added both “London” and “Tokyo” to the list when in fact the first person had removed “London”.

If we are using a 2-way merge tool (Beyond Compare in this case), that might look like this:

You can see that the default result in the bottom pane is not the correct answer and that’s because this merge doesn’t have all the information it needs. Of course if you’re doing a merge, it’s likely you were one of the parties responsible for the changes and can remember what changes you made and can reconcile that with the changes made by the other person. But relying on your ability to remember what you did and properly addressing that in a merge is not a good strategy to avoid making mistakes.

This is where 3-way merging comes in. The difference is that a 3-way merge adds a third file to the mix (not counting the fourth output/result file) which is the common ancestor or base that the two originated from. With this base, you can now separately see what changes were made to create the two files and you can reconcile those two sets of changes more easily.

Here is what that looks like in Beyond Compare:

On the left is the first changed file and on the right is the second changed file. In the middle is the base of both files. Now you can see that “London” was removed from the left file and “Tokyo” was added to the right file. This gives you the information you need to do the merge correctly and in this case, the default merge proposed by the tool in the bottom pane is exactly that.

Unfortunately there are not a lot of free diff tools that support 3-way merges. My diff tool of choice is Beyond Compare from Scooter Software which added 3-way merging in version 3. It is not a free tool however.

Another tool you might consider that I don’t have any personal experience with that does appear to be free is P4Merge from the makers of Perforce.

Aligning Diffs

One last plug I’d like to make for Beyond Compare is a feature I find very useful which is the ability to manually align a diff. Imagine that a developer moves an entire block of code from one place in a file to another place in that same file. A diff of the before and after file is going to show exactly that making it difficult to tell if the developer not only moved the block of code but made changes to it as well.

This is where the align feature comes into play. In Beyond Compare, you can manually tell it to align the top of the block of code in each file and the comparison will start at those lines of code. Then you can see how that block of code compares in each file. Of course the rest of the files will show up as completely different because the align is all wrong but at the moment, you just care about the block of code by itself.

Here’s an example where I’ve moved a paragraph within a file:

I can right click on the first line of the red block on the left and select “Align With…”. Then I can select “With” by clicking on the first line of the block on the right and I get a different alignment:

Now it’s easy to see that not only did I move that paragraph, but I added a word too. Sneaky!

This feature also works if you’re doing directory level diffs with Beyond Compare showing you the differences between folders. You can manually tell Beyond Compare which files to compare. This can be useful if a file was moved or renamed and your default diff doesn’t recognize them as the same file.

--

--