SaschaWildgrube
ServiceNow Employee
ServiceNow Employee

Most experienced developers have at time point in their career worked with a source control system and many of them have been exposed to widely adopted standards like gitflow – which essentially proposes the use of feature branches.

 

The main idea of feature branches is that any separable feature is developed in its own branch and once the work on that feature is completed, that branch is merged back into a master (or default) branch.

 

This approach works under the assumption that source code can be merged by the Source Control System. Merging involves a side-by-side comparison of source code files and the possibility to make decisions about how to inject the proposed changes taken from the feature branch should be ingested back into the master branch.

 

That works fine with traditional source code files, config files, even xml files to a certain extend.

And here is the problem: branch merging does NOT work with all ServiceNow application files.

 

Here is why: Traditional source code is text only.

 

ServiceNow application files are stored as records in the database and once they are committed to the Source Control System, these records are represented as xml files – which do not only contain source code but also meta data and – this is the tricky part – references to other application files.

 

For some application files, like Script Includes and Business Rules – which consist of exactly one record - the process of merging – even when represented as xml files – is working.

 

ServiceNow however provides a growing toolset of low-code or even no-code mechanisms to design and implement application behavior – Flow Designer and UI Builder just to name a few.

 

A Flow is not just a single record, it is represented by a vast network of records, which are tightly coupled and are neither human readable as xml files nor can they be merged by a Source Control System in any meaningful way.

 

Another property of the ServiceNow platform is that an application is always connected to one source control repository branch at any given time. So, if two developers work on the same application on the same instance, they make changes to the same set of records that constitute that application.

 

One may argue about the design decisions made – but that won’t change the fact that

  • Many application files just CANNOT be merged in a Source Control System
  • Multiple developers cannot work on multiple branches of an application on one development instance at the same time

To cut this short: forget gitflow, forget feature branches, forget merging!

 

With that being said, the questions are

  • How can developers work on separate features?
  • How can features be released selectively?
  • What to do if the work on a feature is not yet finished when an application version should be shipped?

The answers to these questions can be found in chapter “Technical Debt Management” and – in more technical terms – in chapter “Managing Unfinished Work” in the whitepaper:

https://www.wildgrube.com/download/A%20mature%20Development%20and%20Deployment%20Process.pdf

 

If feature branches are not an option – how should developers now work with branches? What value do we get from the Source Control System after all?

 

The Source Control System serves three main purposes:

  • To keep a reversible trail of all changes deemed relevant by the development team
  • To store all baselined application versions that were ever delivered by the development team
  • To allow switching between different application versions – that may be multiple versions in development – and all versions that were ever baselined

 

This is how it works:

Each application has its own repository (or “project” in GitLab’s terms) – and this will stay that way even if ServiceNow ever decides to support storing multiple applications in one repository in the future.

 

The default branch in all application repositories is to be named “dev” (most Source Control Systems start with a branch called “master” or “main” when creating a new repository – these branches need to be deleted).

 

The “dev” branch is always the active branch in the development environment.

 

Whenever an application version is baselined, a new branch is created based on the current state of the “dev” branch which is to be named exactly like the version to be baselined.

 

This new version branch is to be locked immediately after being created – no further changes to this branch should be allowed.

 

In case of a hotfix, the existing version branch is installed on an instance, the application is modified, and the new state is stored as a new version branch (which possible represents a lower version than the latest version already stored as a branch).


The instance used to develop the hotfix depends on the instance setup used. Ideally there is a dedicated HOTFIX instance reserved for ad-hoc hotfixing. If such an instance is not available, hotfixes can also be created on DEV or TEST instances (see chapter “Instance Setups” in the whitepaper for more details).

 

By applying these rules, the read-only version branches form the audit trail of delivered application versions by the development team and the single source of truth of anything that will ever be deployed on a downstream instance. Note that applications can only be installed from a branch (not from a tag) hence branches must be used.

 

Developers will always commit their changes to the “dev” branch during regular development.

 

The guidance should be that developers commit all changes made on the development instance as soon as possible – even if they are yet unfinished and not yet ready for deployment.

 

In theory, a team could also commit only finished work and stash any uncommitted changes during application baseline – when a new branch is being created – and then reapply the stashed changes after switching back to the dev branch. Real world experience with two larger developer teams revealed that – although technically feasible – the approach is more difficult to manage and more error prone when executed.

 

For hotfixes, the process is slightly different – please refer to chapter “Hotfixing and Backporting” in the whitepaper.

 

If a development team currently works on a version of an application that is soon to be released (e.g., version “1.x”) and at the same time the next – and backward incompatible version should be worked on (e.g., version “2.x”) – a second development instance is required. The work on this future version would then be stored in a second “dev2” branch – please also refer to chapter “Hotfixing and Backporting” for further guidance on that scenario.

 

The list of branches of an application could look like this:

  • dev
  • dev2
  • 1.0.0
  • 1.1.0
  • 1.2.0
  • 1.2.1
  • 1.3.0
  • 2.0.0
  • 2.1.0

To summarize: ServiceNow application files cannot be merged in a Source Control System and hence any method involving feature branches (e.g., gitflow) is not an option. To allow for selective feature deployments and the ability to always provide new application versions from a “dev” branch, features must eventually be turned off and treated as technical debt.

 

The branching strategy can hence be described best as “commit at head” as all changes are to be committed to the “dev” branch as soon as possible – no matter if the related work is completed.

 

How does all of that fit into a mature development and deployment process?

Download (and read) the whitepaper:

https://www.wildgrube.com/download/A%20mature%20Development%20and%20Deployment%20Process.pdf

 

Version history
Last update:
‎03-21-2025 05:31 AM
Updated by:
Contributors