DaedTech

Stories about Software

By

Merging Done Right: Semantic Merge

There are few things in software development as surprisingly political as merging your code when there are conflicts.

A Tale of Merge Politics

Your first reaction to this is probably to think that I’m crazy, but seriously, think about what happens when your diff tool/source control combo tells you there’s a conflict. You peer at the conflict for a moment and then think, “alright, who did this?”

Was it Jim? Well, Jim’s kind of annoying and pretty new, so it’s probably fine just to blow his changes away and send him an email telling him to get the latest code and re-do his stuff.

Oh, wait, no, it looks like it was Janet. Uh oh.

She’s pretty sharp and a Principal so you’ll probably be both wrong and in trouble if you mess this up — better just revert your changes, get hers and rework your stuff.

Oh, on third look, it appears that it was Steve, and since Steve is your buddy, you’ll just go grab him and work through the conflict together.

Notice how none of this has anything to do with what the code should actually look like?

Standard Diff Tools are Bad at Telling You What Happened

Now, I’ll grant that this isn’t always the case; there are times when you can figure out what should be in the master copy of the source control.  But it’s pretty likely that you’ve sat staring at merge conflicts and thinking about people and not code.

Why is that?

Well, frankly because merge tools aren’t very good at telling you the story of what’s happened, and that’s why you need a human to come tell you the story. But which human, which story, and how interested you are in that interaction are all squarely the stuff of group dynamics and internal politics. Hopefully you get on well with your team and they’re happy to tell you the story.

But what if your tools could tell you that story?

What if, instead of saying, “Jim made text different on lines, 100, 124, 135-198, 220, 222-228,” your tooling said, “Jim moved a method, and deleted a few references to a field whereas you edited the method that he moved?”

Holy crap! You wouldn’t need to get Jim at all because you could just say, “oh, okay, I’ll do a merge where we do all of his stuff and then make my changes to that method he moved.”

Introducing Semantic Merge

I’ve been poking around with Roslyn and reading about it lately, and this led me to Semantic Merge. This is a diff tool that uses Roslyn, which means that it’s parsing your code into a syntax tree and actually reasoning about it as code, rather than text (or text with heuristics).

As such, it’s no mirage or trickery that it can say things like “oh, Jim moved the method but left it intact whereas you made some changes to it.” It makes perfect sense that it can do this.

Let’s take a look at this in action. I’m only showing you the tiniest hint of what’s possible, but I’d like to pick out a very simple example of where a traditional merge tool kind of chokes and Semantic Merge shines. It is, after all, a pay to play (although pretty affordable) tool, so a compelling case should be made.

The Old Way

Before you see how cool Semantic Merge is, let’s take a look at a typical diff scenario. I’ll do this using the Visual Studio compare tool that I use on a day to day basis.

And I’m calling this “the old way,” in spite of the fact that I fell in love with this as compared to the way it used to be in VS2010 and earlier. It’s actually pretty nice as far as diff tools go. I’m going to take a class and make a series of changes to it.

Here’s the before:

public class SomeClass
{
    private int _aNumber;
    private string _aWord;

    /// 
    /// Initializes a new instance of the SomeClass class.
    ///
    public SomeClass() 
    {
      _aNumber = 123; 
      _aWord = "Hello!"; 
    }

    public void PrintNumbers() 
    {
      for (int index = 0; index < _aNumber; index++) 
        Console.WriteLine(index); 
    } 

    public void PrintEvenNumbers() 
    { 
      for (int index = 0; index < _aNumber; index += 2) 
        Console.WriteLine(index); 
    }
   
    public void ChangeNumber(int number) 
    {
      if (number < 0) 
        throw new ArgumentException("number"); 

      _aNumber = number; 
    } 

    public void PrintTheWord() 
   { 
     Console.WriteLine(_aWord); 
   } 
   
   public void ChangeTheWord(string newWord) 
   {
     _aWord = newWord; 
   }
}

Now, what I’m going to do is swap the positions of PrintNumbers() and ChangeTheWord(), add some error checking to ChangeTheWord() and delete the comments above the constructor. Here’s the after:

public class SomeClass
{
    private int _aNumber;
    private string _aWord;

    public SomeClass()
    {
        _aNumber = 123;
        _aWord = "Hello!";
    }

    public void ChangeTheWord(string newWord)
    {
        if(string.IsNullOrEmpty(newWord))
            throw new ArgumentException("newWord");
        _aWord = newWord;
    }
        
    public void PrintEvenNumbers()
    {
        for (int index = 0; index < _aNumber; index += 2)
            Console.WriteLine(index);
    }

    public void ChangeNumber(int number)
    {
        if (number < 0)
            throw new ArgumentException("number");

        _aNumber = number;
    }

    public void PrintTheWord()
    {
        Console.WriteLine(_aWord);
    }

    public void PrintNumbers()
    {
        for (int index = 0; index < _aNumber; index++)
            Console.WriteLine(index);
    }
}

If I now want to compare these two files using the diff tool, here’s what I’m looking at:

StandardDiff

There’s a Better Way to Handle This

This is the point where I groan and mutter to myself because it annoys me that the tool is comparing the methods side by side as if I renamed one and completely altered its contents entirely.

I’m sure you can empathize. You’re muttering to yourself too and what you’re saying is, “you idiot tool, it’s obviously a completely different method.”

Well, here’s the same thing as summarized by Semantic Merge:

SemanticMergeDiff

It shows me that there are two types of differences here: moves and changes. I’ve moved the two methods PrintNumbers() and ChangeTheWord() and I’ve changed the constructor of the class (removing comments) and the ChangeTheWord() method.

Pretty awesome, huh? Rather than a bunch of screenshots to show you the rest, however, however, I’ll show you this quick clip of me playing around with it.

Some very cool stuff in there. First of all, I started where the screenshot left off — with a nice, succinct summary of what’s changed.

From there you can see that it’s easy to flip back and forth between the methods, even when moved, to see how they’re different. You can view each version of the source as well as a quick diff only of the relevant, apples-to-apples, changes.

It’s also nice, in general, that you can observe the changes according to what kind of change they are (modification, move, etc). And finally, at the end, I played a bit with the more traditional diff view that you’re used to — side by side text comparison.

But even with that, helpful UI context shows you that things have moved rather than the screenshot of the VS merge tool above where it looks like you’ve just butchered two different methods.

This is only scratching the surface of Semantic Merge. There are more features I haven’t covered at all, including a killer feature that helps auto-resolve conflicts by taking the base version of the code as well as server and local in order to figure out if there are changes only really made by one person.

You can check more of it out in this extended video about the tool. As I’ve said, it’s a pay tool, but the cost isn’t much and there’s a 30 day trial, so I’d definitely advise taking it for a spin if you work in a group and find yourself doing any merging at all.

By the way, if you liked this post and you're new here, check out this page as a good place to start for more content that you might enjoy.
3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Doggeti
Doggeti
9 years ago

This is very interesting. I really have to get my hands on Roslyn soon. I strongly feel that it will revolutionize many aspects of software development.

Erik Dietrich
9 years ago
Reply to  Doggeti

I tend to agree. If you’re so inclined, I wrote a blog post last week about Roslyn itself aimed at getting people started. And stay tuned, I’ll post more about it as I play with it, myself. We can check it out together 🙂

trackback

[…] Merging Done Right: Semantic Merge [Erik Dietrich] […]