I’ve been thinking about source code management, because I recently encountered two very different approaches to it. Let me begin with a quick overview of some key source code management terms and concepts. First, what do I mean by source code management (SCM)? SCM is the art and science of controlling the source code for a project/product. Control includes concepts like: allowing developers simultaneous access to code so they don’t conflict with each other while innovating; allowing maintenance for current releases to occur while innovation continues on the main project/product line; having instant access to a version of delivered source code; keeping a detailed history of all changes made; and providing rollback capabilities should changes need to backed out [Obviously, this is my laymen’s definition. Here is a better definition and a pretty good summary of SCM: https://www.cio.com/article/120802/Source_Code_Management_Systems_Trends_Analysis_and_Best_Features].
SCM usually involves a SCM system like Subversion or Git to enable versioning, locking and general control of the source code files. SCM systems provide two very important concepts that enable good management of source code: tags and branches. Every SCM system implements these concepts differently, but in general, they work like this: a tag is a bookmark in the codeline, like “release 1.0” or “beta release 3.3”. These bookmarks allow developers to quickly and easily retrieve a specific version of the entire project/product from the SCM system. A branch is simply a copy of the main codeline (usually referred to as the trunk) that is set aside for independent maintenance or development.
I mentioned above that I recently encountered two different approaches to SCM. The first approach I view as the more “traditional”: all work is done on the main (trunk) codeline, and tags, branches, and code merges are used to manage releases and bug fixes. Figure 1 depicts this approach graphically.
Figure 1 The “Traditional” Approach to SCM
In this approach, a tag (denoted as “T” in the figure) is created for each released version of the codeline, and branches (denoted as “B” in the figure) are created for each major release. Bug fixes made in released codelines are merged (denoted as “M” in the figure) back into the trunk codeline to keep it current. As you can imagine, if you are maintaining numerous releases of a product concurrently, your branches can overlap significantly. This will inevitably result in merges occurring in parallel codelines in addition to the trunk codeline.
The advantage to this approach is that all innovation is done on the trunk codeline and developers can easily retrieve the latest code from the SCM system to update their development environments. Meanwhile, maintenance can continue on released versions of the codeline. Tags are used to denote released versions of the code. For example, a developer can easily request version 2.1 from the SCM system to patch a bug in that release of the software. In Figure 1, version 2.1 represents a branched version of the trunk codeline. When bugs are fixed in branched codelines, the fixed code must be manually integrated back into the trunk codeline. This process is referred to as a code merge and can be a daunting process. However, this ensures the trunk codeline benefits from all the bug fixes that occur in the released versions. As you might guess, depending upon the number of concurrently supported releases of a project/product, a lot of code merging may be required to integrate bug fixes into the trunk codeline (thus the “art” of SCM). This model has — and does — work well for most projects/products.
However, some cases require that you take almost the exact opposite approach as that described above. In these cases, you create a branch for innovation and keep your trunk codeline only for bug fixes. When bugs are fixed, they are merged with the active development branch(es). When innovations are made, they are “cherry picked” out of the innovation codeline and merged back into the trunk codeline. Figure 2 depicts this approach graphically.
Figure 2 The “Solution” Approach to SCM
In this scenario, the 1.0 trunk codeline is branched for customer A. Not long after the initial branch, bug fixes are merged from the trunk codeline into the customer A codeline (denoted as “M1” in the figure). Once feature 1 (denoted as “F1” in the figure) has been implemented in the customer A codeline, it is integrated back into the trunk codeline (denoted as “M2” in the figure). This process continues. Notice how feature 2 (denoted as “F2” in the figure) is integrated back to the main codeline from customer A, and then integrated into the customer B codeline (denoted as “M5” in the figure).
This approach is more common on projects that involve what I call “solutions”. Many consulting companies offer potential clients “solution frameworks” for common problems. These solutions are essentially prebuilt – but not complete – frameworks that address specific problems. Every implantation is a “one off” from the original codeline. For example, suppose a company offers a case management solution. This solution may contain 80% of the infrastructure, data schemas, services, APIs, workflows, etc. to implement a generic case management system. However, 20% of the system must be tailored to meet a client’s specific needs. Suppose the basic solution knows how to manage and relate all the files in a case to one another, but CLient A needs the ability to aggregate similar cases. This functionality is not part of the solution and must be custom developed for this client. However, this is a capability that might be appealing to other clients as well, so after it is developed, it is merged back into the trunk codeline of the solution framework.
Are there other approaches to SCM? Yes, of course. For example, you could easily imagine a hybrid of the two approaches described above where each custom codeline adapts a tag and branch approach to manage versions within its codeline. Merging changes back to the custom codeline and the trunk codeline could be nightmarish, but possible. Is SCM really this simple? Yes and No. Much depends upon your development rhythm, release cycle, development team, customer requirements, etc. This article paints a broad picture of two SCM approaches, the implementation details of either of these approaches requires good planning and policies.
What I learned from my exploration SCM approaches is that there is not necessarily a right or wrong approach. With the advent of sophisticated SCM systems (e.g., Subverison, Git, etc.), much of the “science” of SCM has given way to the art, the art being: determining how to best leverage the capabilities of the SCM system to support the way you, your development team, and your customers work.