Patching vs. Merging

One of the biggest complications of software development across multiple people is keeping things in sync and making sure contributions don’t conflict with one another. The desire to solve this has spawned countless tools, development concepts and cycles along with a plethora of case studies by bored middle-management. The most common tools to help with keeping things in sync these days are git and svn, which provide versioning of code and tools to maintain code across multiple people and multiple development points. With git being the most widely used now a lot of projects have started to switch to it, the same was true for OpenSimulator years ago, moving from svn to git. Over the years the git ecosystem spawned a number of useful tools that certainly helped to move development of a lot of projects forward by making things easier to maintain and merge, but not every part of course.

Permissive open-source projects, such as OpenSimulator, provide the ability for anyone to create their own flavors, making changes they would like to see and adjusting their experience accordingly. Traditionally this is done by taking the existing code repository and making changes directly, subsequently being faced with the prospect of merging the changes made by the original author of a project back into theirs. While not a big deal for minor changes, the larger a project becomes the more difficult this task can be and it’s not fast or intuitive either. Like with most things surrounding git, there exist tools to help make the merging process easier and git itself is designed to try and merge code as best it can to leave on the most grave differences up for human review. However, therein also lies a potential for software, making assumptions about “correct” code, creating a complete mess. The more such a project, commonly referred to as a fork, diverges from the main project, the more complex such merge operations can be for both software and the human maintaining the fork.

This style of merging is the more prominent method most employ to maintain their forks of projects, but in the cases where merging the main code back into their projects ends up being a bigger task than the changes ever were to begin with another option might be less problematic and time-consuming. Git allows for any change to become a patch file, which contains just the change and instructions for git to merge the respective code into where it was changed. This, despite being tied to a specific file and position, can still take advantage of merging tools and operations, allowing a patch to be applied so long as the surrounding code matches. Meaning a patch created from a code change can be applied to many different versions of a project so long as there were no other changes to the same code. Obviously this makes maintaining changes in a rapid development environment a lot easier as there is no longer a need to merge every change and review for any mess that might have been caused. Patching in this manner isn’t free of problems, but the done changes compared to the patch itself is easier to review.

Applying such a patch stack to a project like OpenSimulator isn’t a solution without work involved as there are conflicts from time to time and changes elsewhere in the code can have an impact, especially when functions change or code standards require rewriting of existing patches. However, especially in regards to rapid development and testing both features and bugfixes in a manner not requiring large code merges and reviews has been vital to reducing the workload of maintaining a fork while still providing active feedback and development back to OpenSimulator. While traditional merging makes sense for projects that have slower development cycles or forks that only follow larger releases on bigger timescales, for anything that moves faster and needs changes to make it into the codebase in hours rather than days using patches usually remains the better way to go. Of course there is never an ideal solution when dealing both with code and humans in a mix trying to develop and maintain two separate, but connected and dependent, entities.

The flexibility of patching and the rapid development cycle of OpenSimulator, though, seem to be a better match than merging. Especially the flexibility to tailor OpenSimulator to the individual requirements of customers through leaving certain patches out or adding special ones in, while still being able to relatively easily stay up to date, has sold us on this approach. For less complex projects, like some of OpenSimulator’s dependencies, we still employ merging as well, given the changes are minor enough that merge conflicts are nearly impossible. Something as complex as OpenSimulator itself, however, other forks and projects have shown merging to only function in longer time frames as there is just too much code to review as development continues to progress on an almost daily commit schedule.