In 2005 I was in charge of software development for a web shop. Our client wanted to improve time to marked for new features, and has therefore requested to develop several features in parallel. Well, this was a web site based on the ASP.NET technology, and I wasn’t enlightened enough at that time to break it up into smaller vertical modules, so that the whole thing was consisting from several horizontal modules (layers), and all of them had to be updated for each new feature. Each module compiled into one dll file. Therefore, the only way to develop AND release several features in parallel was using branches.
Now, branching was very easy and straightforward with the version control system we were using. Just like about any other VCS in the world. The problem was that branching always implies merging. And everybody knows, merging is a hell on earth. And just like that, I went to the client and explained that his request would put us in the hell, and so development from hell will cost him more money. Fortunately, he abandoned this idea.
This approach to merging I’ve managed to retain up until 2011. In 2011, we’ve started using git. At that time, I was working together with a colleague (hi Martin!) on a C source base, and we didn’t have the notion of code ownership, and often even haven’t decided upfront who is working on what part. As a result, we’ve got to merge quite often, and it was surprising for me to learn this:
If you know how to merge, it is not harder than, say, debugging or refactoring. And neither it is more risky.
Let’s discuss first, how the subjective impression of merging being hell would be typically created.
When a software developer compiles and runs an app, he naturally expects bugs to appear. And when they indeed manifest themselves, he is thinking “oh well, no miracle this time either, ok, let’s see” and routinely launches a debugger. He’s in a working context, and his brain is in active thinking mode.
When a software developer performs a refactoring, it is somewhat similar. His code stinks, so he goes grab some more coffee, scratches his head, draws some new architectures on a piece of paper, and then launches his favorite refactoring tool. Still, working mode, nothing fancy.
Now, think about your very first merge experience. Mine was like this: I was done with a task, and wanted to commit it to repository. And then, the VCS has shown me this “you have to merge first” notice. Now that was unfair. That was a punch below the line. My brain was already in the power saving mode. I was already thinking about a little pause. I was almost done, dammit! I was almost done, VCS, and now you’re fucking telling me I’m far from being done!?
Hesitantly, I took a brief first look at the 3-way merge tool. It looked scary, and promised several hours of intensive thinking just to learn it and to understand how it works. So that I’ve discarded the server changes, overwritten them with my local changes, and commited the merge. What I didn’t know, is that this another change made by some other person was very important. And they already have reported to the top management that this change was ready and could be rolled out in the next release. My lazy merging has effectively reverted this change.
Ouch! That hurt.
Now, remember reflexes, and the Pavlov dogs? If something hurts, we tend to avoid it, or at least do it not very frequently. The perfect trap is closed, and the merge wins. The 3-way merging tool goes back into oblivion with his secrets remaining unexplored, and re-appears only in software developer’s nightmares.
But let’s look at the merging objectively. It consists from reading and understanding source code, and editing source code – mostly by applying ready patches, which is today in the times of StackOverflow and Google Oriented Development not very different from writing new code, or performing just about any other software development activity.
Is the only reason why merging is harder and riskier, because we’re not doing it often enough?
The often we merge, the better we learn how to do it. And more training makes just about anything easier to do. But it is not only about training and knowing how to use the 3-way merge tool. Especially in the merging case, doing it more often has additional two game-changing implications: you’re reducing the merge scope, and you start using tools that are better suitable for merge.
In the next blog post, I’ll share what I have learned about merging techniques.