Effective Code Base Management
If you’re considering whether or not to introduce code base management process into your organization, let us save you a tremendous amount of time.
Code base management is an absolute necessity for running an effective digital production department.
Great, now that we’re aligned, let’s look at how to go about it.
Code Base Management has two aspects:
- A process for managing the source code itself (the files within your projects), and
- Processes for managing file revisions
Central to both processes is the use of a version control system. With a version control system, your team creates a central repository (sometimes referred to as “repo”) for each project that allows files to remain organized, facilitating transparent and easy history management, notation, and merging.
While a version control system might seem like overkill when your team is small, or if only one developer works on one project at a time, there is actually no situation where version control will not save you time and money.
Moreover, the costs and problems that stem from no version control increase exponentially as you add more developers, more projects, larger or distributed teams, or seek to operate your teams with flexibility (i.e. have team members come in and out of a project). In short, growing your department successfully without version control is impossible.
Some common fires that arise from ineffective code management include:
- team members not being able to work on similar areas of the project at the same time
- excess communication to avoid collisions or developers constantly bumping into each other and creating confusion
- files being overwritten, changes lost
- regression of code, and random errors “coming back”
Which Version Control Solution should I use?
Any version control is better than no version control. But there are plenty of different version control solutions to choose from.
The differences are subtle, especially for someone who is non-technical. From the oldest modality CVS, to SVN, Git and Mercurial, each have their own twist on how they handle file versioning, branching and mergers. The best thing to do is to consult your technical lead (and entire team) and openly consider the pros and cons of each solution.
Sometimes your team will already be quite used to one solution or another, in which case the choice is easy. If there is no familiarity, and you are starting from scratch, here’s a quick look at the two most popular solutions today.
SVN
SVN was developed by the Apache Software foundation to improve on CVS (the original version control system).
Pros:
- Centralized server where code is maintained
- Atomic operation means a change is fully integrated, or completely ignored
- Large community, and variety of plug-ins for editing software
Cons:
- Has some problems with renaming files and directory
- Not a great level of management control for the repository
- Kind of slow compared to others
- Must have access to server to make changes
GIT
Started by Linus Torvalds (“father” of Linux), Git has a very different approach to SVN and CVS (by intention). Mainly it functions peer-to-peer and each instance maintains a full history of changes, making it possible to work offline, or when disconnected from other peers.
Pros:
- It’s fast. Real fast
- Full history tree available when not connected
- Operations on branches are cheap
- Peer-to-peer model, there is no central server required
Cons:
- More difficult to understand and get used to than SVN
- Windows support is not that great
Both SVN and Git have thousands of miles proving their capability to manage software and web development solutions. They’re both free, have loads of community support and plenty of supporting documentation.
Once you’ve determined which type of version control system you want, you’ll need to pick the provider to host your source files and the software to use to interact with the repositories.
As of this writing there are hundreds of providers and dozens of clients available, so to keep things simple we’ll give a little plug to our current favorite: Bitbucket.
Bitbucket offers a full ecosystem for hosting repositories and management through their client SourceTree. The client is cross-platform and quite user friendly. Their services also include hosting both SVN and Git repositories.
The Process of Source Code Management
Once you’ve settled on a version control solution, and have selected the provider and software your team will be using, you must now create a process which your team follows to manage code commits and revisions.
- How do we branch?
- How do we make updates?
- How do we commit?
These are all very important questions to be sure, and answering them through a documented process will ensure your department enjoys the maximum potential of version control.
As with project management methodology, there are countless ways you can approach the version control workflow. Again, it’s less important to pick the “right” one, and more important to have one approach that is clearly defined and diligently followed. In fact, we recommend picking and choosing the aspects you like from different methodologies and bringing them together into your own recipe. If you find something lacking or need extra provisions for the specific nature of your organization, add those in liberally. There’s no benefit to creating a process that is not internally sustainable!
Version Control at The Development Factory
After developing hundreds of projects with dozens of developers across multiple (less than ideal) scenarios, we’ve learned a few things about what makes version control work.
Below is our own process directly from The Development Factory playbook. If it works for you — go ahead and make it your own!
Core Branches
At the start of every project we create the same three core branches and set up access rights and control privileges for each of them. Before we can do that though the repository has to be “initialized.”
Here’s the steps taken by the technical lead to initialize any project:
- Create the repository according to a standardized naming convention
- Make the first commit to create the master branch (this is usually the README file explaining the project, or more typically a copy of a boilerplate project with the README file then customized)
- Create “develop” and “staging” branches, and ensure all three core branches are not deletable, and cannot have their history re-written
- Add appropriate teams, or team members to the project
- Configure access rights per the three core branches, i.e. only allow certain developers to merge into the core three (if there should be anyone else other than tech lead that has this capability)
The three core branches, “master,” “staging,” and “develop” are used to correspond to different hosting environments, and can be tied to automatic deployment methods to each of these environments.
Master
The master branch corresponds to the live (or production) environment and is the branch updated least frequently. Access to merge into this branch should be given out with care. Automatic deployment from this branch is possible, like with all other branches, but not recommended. Deployment should always be manually triggered to ensure timing and absolute control over the process.
Merges into the master branch should only ever come from the staging branch. The only possible exception is a hotfix (covered later), but even so if the hotfix is not checked / validated on staging, it’s a risk to deploy directly.
Staging
The staging branch corresponds to the client staging environment (sometimes referred to as UAT — User Acceptance Testing). This is the final checkpoint before any code is merged into the master branch and deployed into a production environment.
Staging merges are not frequent, but should still happen every 1–2 weeks throughout a project lifecycle. You don’t want to leave too much room between progress reviews or problems will start to pile up, and it becomes more difficult to separate fixes from improvements requests.
Staging environment updates should be automated — meaning any update / merge into the staging branch should automatically update the staging build. Access to merge should be given out with care, and would ideally be limited to the most senior members of the team.
Develop
The develop branch is the most frequently updated branch, sometimes receiving multiple merges in a single day. This is the focal point for combining work from multiple team members and / or different features and bugs being worked on concurrently.
In more advanced setups, the develop branch is tied to automatic unit testing and deployment. Thus a deployment to the development environment is not completed unless the merged code successfully passes linting (code format checks), code coverage (the degree to which test cases exist for all of the functions within the code), and unit tests (the actual tests of code themselves). It’s possible to extend these tests into the feature and fix branches developers work on as well so the merger itself cannot happen unless tests pass.
While this is all recommended, it is difficult to achieve this level of testing and automation. Especially when under constant pressure to deliver (i.e. all the time!). This is why following the staging merge processes are important, so that there is some level of QA / checking before something is “published.” Access to merging into the develop branch is usually limited to senior developers or code quality control teams (on larger projects).
Automating tasks allows you to slowly build up your version control infrastructure and process to gain greater and greater levels of confidence when delivering code, and minimize the amount of billable hours spent testing.
Conversely, while automation can take on a lot of the necessary checks, if you really want to make sure things are smooth you should always maintain certain checkpoints with real people. Code checking is also a useful way to train up developers who you are looking to promote from junior or intermediate roles to more senior roles, or when integrating new people into your team entirely to ensure they are following your best practices!
What if there’s only one developer?
Version control is important no matter the circumstance, and so is following process. While having additional branches, as we describe below, is not necessary, the three core branches should always be created and tied to the three environments.
With only one developer working on the project they would typically commit directly to the develop branch, and manage mergers from develop to staging, and from staging to master themselves. However, if you have multiple developers on your team, it’s strongly encouraged that a different developer manages merges from develop to staging and staging to master, even if they are not involved on the particular project. Four eyes are still better than two.
Managing the Workflow
With the core branches configured, your team is ready to start working on the project.
In most cases work is broken down and assigned using an outside ticketing system (learn more about ticketing processes here). As the project evolves, more tickets emerge. These tickets can be categorized as features, most of which are known at the start of the project, and bugs, most of which emerge as the project evolves.
First, and foremost, a developer should never work on anything unless there is a ticket for it. Never. This is one of the most important rules within the process, and ensures there is a clear trail to everything that’s been done on the project. It additionally makes sure that each feature or bug is tested, based on the ticket, which is based off of the original request. It “closes the loop” on the work.
Once tickets are in, categorized, prioritized and assigned, developers can start branching off from the develop core branch and get to work. While it’s ideal to have each pull request / merge correspond to a single request, it’s also OK for the developer to combine multiple tickets into one branch and pull request, as long as the tickets that have been addressed are clearly identified in the commit message.
feature/feature_name
All features should be created within the sub branch “feature” with an appropriate name. For example “feature/modify_user_profile”, or “feature/archivability_of_projects.” Once the feature is complete and tested by the developer a pull request can be created to the develop branch.
fix/fix_name_or_date
All bugs should be created within the sub branch “fix” and should also correspond to what’s being fixed, for example “fix/cannot_delete_project,” or “fix/dashboard_not_loading.” Sometimes the number of bugs or turnaround time for fixes is very short, and it might be easier to organize bugs by time period (of when they were reported), for example “fix/from_review_apr13”, or “fix/for_apr17”. Once the fix or fixes are complete and tested by the developer a pull request can be created to the develop branch.
hotfix/fix_name
There can also be the special case of addressing urgent fixes — which need to be deployed to the live environment as they are causing problems for current users. In these cases a hotfix branch can be used, and created directly off of the master branch. For example “hotfix/project_screen_broken,” or “hotfix/cannot_log_in.” Pull requests from these branches go directly to master, so they can be deployed immediately.
Managing Conflicts
When there are a number of developers working on a project, even when it’s well organized by the tech lead in terms of who does what, inevitably conflicts within the code can arise. This is where version control really shines and helps avoid disasters.
While it is possible to resolve a conflict as part of the merger, the best policy is to avoid it altogether by letting the developer making the pull request resolve the conflict themselves, before making the pull request. This is done by the developer first merging the target branch into their own feature or bug branch, and then doing a pull request.
For example, if I am working on “feature/deleting_projects,” when I am done the work and have made all of my commits, I first pull the “develop” branch into my branch, and then submit the pull request to “develop.” Pulling “develop” means that any conflicts are identified at this point, and me, as the developer is responsible for resolving them properly, before making the pull request.
This method should also be used when merging between the three core branches. That is before you do a merge from “develop” to “staging,” or from “staging” to “master,” you first pull the other way, resolve conflicts, and only then merge.
Conclusion
Moving to a version control solution and code management process can be difficult when you have never done it before. However, the benefits gained with visibility, tracking and minimizing errors are immeasurable.
Whether you have a small team, small projects, or even just one developer, you must create an effective code management approach.
Got tips for us on how to improve code base management? Tweet us @devfactoryLA