14.9 Version Control
Developers don't work on a single, monolithic application. The team delegates out tasks so that different developers will be working on different parts of the application simultaneously. Work done by different team members at different times will come together to enable a single new feature or update. The lead engineer or engineering architect will manage how these different portions of work are broken up and delegated out. Specialized source code management (SCM) software is used to orchestrate who is doing what with which versions or branches of code and to determine when a portion is effectively locked and released as a build.
The SCM is the domain of the engineering team, but a product manager needs to understand how it works. That's because code management issues will affect product decisions—judging launch-readiness of a feature, implementing bug fixes, testing upcoming changes, and weighing the risks of working on certain functionalities in parallel. In this checkpoint, you will learn the terminology surrounding these issues; becoming fluent in it will allow you to follow discussions with the development team as you collaboratively build a product.
By the end of this checkpoint, you should be able to do the following:
- Explain basic source code management and version control concepts
- Discuss relevant implications of these concepts on product development
The different versions of your application
Imagine you're the PM on an iOS mobile app. It's not just a single application. The development team is juggling several versions of the app:
- There is an iOS application that's available for download on the Apple App Store.
- There is an updated version of the iOS app that you submitted to Apple for review but that has not been approved yet.
- There is a version of the iOS app that's in development with a new feature.
- There is another version of the iOS app that's in development with some critical bug fixes.
- There is the version of the backend that's live today supporting the iOS app.
- And there's a new version of the backend in development with features to leverage soon-to-be-available iOS features.
There could be even more, but this example makes the point: a variety of versions of any single app exists, and all of these versions must be supported. How does a team keep track of these versions and all of the underlying code?
Versioning and environments
Software versions refer to specific instances of your deployed (or soon-to-be-deployed) product. Developers might also call these builds. The production build or production environment of your software is the one that is live online and currently being used by end users. This is also often referred to as the live version.
Applications will continuously have new versions of the code being updated. Environments are different; they are tiers of development that remain steady. Before the production environment, testing and development happen in the staging and development environments. A version of code will start in a development environment and will eventually move into the staging and production environment.
We'll address this progression in more detail below, but, first, it's important to understand how code is branched and merged back into the source code.

Branches and merging
Developers will refer to different versions of the code as branches. A branch is a specific version of your application's code—and possibly only specific files of the overall application code. When developers are working on multiple features at the same time, there are numerous branches in development at the same time. When working on a bug, developers will take a branch from production in order to work on the same code that is causing the bug. That way, they can find a fix for the version that's in production; the same fix may or may not work for the next version you're preparing. Tracking where branches came from is crucial to ensure that updated code is safely integrated back into the source code.
The most up-to-date version of the application is often called the master version (or just master) by developers. As developers submit new code or changes, they are added to the master. This means that the master version is usually a little bit ahead of the production version because it has unreleased features.
When a developer is done updating the code on their development branch, they merge or check in their changes into the master branch. This process reconciles the differences between the developers' changes with the code in the master version. Between the time when the developer started working on a feature to when it's finished, there might have been many other changes in the master branch to the code the developer was working on. Much like a word processing application that compares two documents and points out the differences, when you are merging branching code, the system will call out conflicts—instances where the code diverges. Once all of these conflicts have been resolved and the updates have been merged in, that new version becomes the master for the given environment. The term build is often used to refer to this. For example, a developer may say something to you like, "We just released build 5.1.3 in the staging environment. It included all of the team's changes from versions 5.1.2.3 through 5.1.2.9."
Preproduction
Before a product goes into production, developers work on preproduction versions. Depending upon the organization, there will be different levels of preproduction as changes progress in readiness to be released (launched). The most common preproduction versions are staging and development (dev) environments.
Prior to staging, developers will run a version of an application on their own computers and devices. These dev environments are branches that developers can link to fake or anonymous data. This enables them to create and test features while maintaining user privacy. Developers are able to work on new features within the existing code while keeping their changes isolated. It is easier for them to work on their own changes without getting tangled up with changes by other developers.
Developers will ask you to check out how they've implemented a feature in their developer environment. This is a useful way to provide feedback and work through any questions very early in the development process. Since these environments are hosted on their computers, they will provide instructions to access and use the test version. It will likely look and feel quite different than the production version, but you will recognize the framework of your product and be able to test specific functionality.
The staging environment is the about-to-be-production version used for final feature testing, full stack testing, and promotional demonstrations. This environment may use real data from your production system, or it might have data specifically for testing. Product management, the QA team (if you have one), and others (such as representatives from marketing or account management) will be able to try the new changes and ensure their functionality before the staging code is pushed into production (this is often called goes live). It's a good practice to have a variety of people from within your company explore versions on the staging environment; fresh eyes on the product will often spot bugs and can provide useful feedback as you prepare to launch the feature.
Releases and patches
After testing and discussions, the team will determine if a feature is ready for release. Your developers will create a release branch of your application. To your marketing colleagues, a release is about the features that can be promoted. To your developers, a release is a snapshot of the entire code at a specific point in time. That snapshot is used to create an updated production version of the application. That release will usually get deployed to a test server. After additional testing confirms the application is behaving as desired, the release will be deployed into production.
No more changes are made to that release unless there's a problem. For example, a bug might be identified during the final testing or in your production application. If that happens, your developers will fix the bug in the master branch with a patch—a piece of code that fixes the bug. The patch will also be merged into the release branch. Because the master branch may be a bit ahead of your production version, if you just fixed the code in the master and released that, you might also be releasing new or incomplete features you didn't intend to release. The updated release will be put on a staging server to validate the fix. Once it's validated, the production version will be updated with the fix.
Supporting old versions
A company has to decide which versions it supports and when a version will become unsupported. This mostly applies to desktop and mobile applications since in those you have less control over your users upgrading to the most recent versions; users of web applications will always load the most recent version directly from your web server.
Old versions are often unsupported because testing for outdated versions is expensive and doesn't contribute to improving the product. For example, if a user is having problems because of a bug in your application and they are using a version that's more than two generations out-of-date, it's likely that the company will have ended support for that version. The current version likely addressed the bug. Customer support would not seek a development fix but would advise the user to upgrade to the current version to resolve their issue.
Users may be on older versions because they haven't (or can't) update their applications. In these cases, buyers will include contractual obligations requiring companies to support old versions. This happens with B2B software and enterprise applications. For various reasons, large companies are reluctant to upgrade software. The biggest deterrent is the potential for new bugs, disruption to their workflow, and the downtime needed for deploying upgrades.
There are a few possible paths for your company to take on how to handle old versions.
- Support older versions. There may be contractual obligations. If so, a product manager needs to be involved in establishing what sales and legal teams can legally obligate the company to do. Be ready to make the case for the added expense and nonprogressive effort that goes into supporting outdated software. A similar logic also applies for B2B companies that create custom versions of software for specific customers; you may have to support those customizations long after the features have become obsolete.
- Use backward compatibility. You can adapt your application to ensure old versions are compatible with new versions, like how new versions of the Windows operating system can run applications made for older ones or how new versions of Microsoft Word can save documents in a format that older versions of Word can process.
- Make old versions obsolete. You can establish a policy that your product will only support the current version or possibly one version back. When choosing this route, it's important that the application gracefully handles the situation. It can be as simple as a message and link to the upgraded version.

Version naming
When you release a big change to an application (or if you have released a bunch of small changes and want to celebrate the updates), it helps to give your release a name. Your developers may have internal ways of versioning their application with complex numbers like 4.3.5-1. That's fine for internal use, but it is not effective with your users.
A good practice is to use a natural sequence of names for the public-facing release names, such as month and year or an alphabetical sequence. For example, you can name your releases after bird species starting from A to Z like Albatross, Buzzard, Condor, and so on. Any sequence of numbers works well too; Chrome releases are numbers like 42 or 77. Just make sure that your release names make sense to all users. Salesforce uses the year and season for their releases, but that can be confusing since the seasons are based on North America.