There may be times when rapid prototyping is more valuable than production stability — for example, in the early days of a service’s creation, or in the event of an operational issue, or if the service performs background tasks that aren’t customer-facing.

In situations like these, code review becomes a hindrance instead of a help. Indeed, there are times when “Does this change work in practice?” will be the first question on a reviewer’s mind. With enough effort, of course, anything can be tested in pre-production environments, but doing so in an early, experimental phase isn’t always practical or worthwhile.

But if we skip code review before build and deployment, when does the code actually get reviewed? Most git tools are designed for a pre-merge, pre-deployment review process; once a change is in master, it’s never looked at again.

In this article, I propose an addition to the standard trunk-based workflow using a new branch, the flux branch. Changes in the flux branch go out to production, but aren’t considered “final” until flux is merged to master. This allows for code review to take place during a pull request from flux to master.

During the development cycle, builds from both master and flux will go out with an identical change history — master+flux — to ensure the code running in production is always in a known, consistent state. Then, once the code has been accepted in review, flux is merged to master and standard trunk-based development resumes.

The flux branch workflow

The flux branch is a short-lived branch designed to supplement a trunk-based workflow.

Development starts by cutting the flux branch from master. As the developer(s) working on the flux branch make commits, they pass through automated linting and testing steps, but are not reviewed before deployment.

While the flux branch exists, all builds from flux and master should go out with an identical history, with flux automatically rebased onto master at build time. This way, no matter which branch build is triggered, the same code is deployed — even if master diverges from the original flux point during the course of development.

Once flux is ready for review, the developer(s) working on flux should rebase it against master for ease of comparison and merging.

After a successful review, flux should be merged (fast-forwarded) into master and then deleted.

Work can continue in the normal trunk-based fashion until such time as it is determined that a new flux point is needed, and then the process starts again.

Automatic rebasing in Jenkins

The flux branch workflow hinges on the build system performing automatic rebases on both master and flux builds.

Since I use Jenkins as my build system, there’s one extra consideration: by default, branch and project scanners won’t configure refspecs that include remote branches. You’ll want to configure the scanner to work with remote branches.

Here’s some example Jenkins library code to do the rebases on build.

def autoRebase() {

    // It's necessary to set up an identity for the CI server
    // for when master diverges. otherwise, git refuses to rebase.
    sh('git config --global user.email "ci@awk.space"')
    sh('git config --global user.name "ci"')

    if (BRANCH_NAME == 'master') {
        def branches = sh(
            script: 'git branch -a --format "%(refname:short)"',
            returnStdout: true
        ).trim().split("\n")
        if ('origin/flux' in branches) {
            sh('git rebase --empty=keep HEAD remotes/origin/flux')
        }
    } else if (BRANCH_NAME == 'flux') {
        sh('git rebase --empty=keep remotes/origin/master')
    }

    // Useful to verify that the recent commit history looks right.
    sh('git log -10 --oneline')

}

A side effect of this is that builds will fail if the rebases cannot be performed automatically. In those cases, flux should be manually rebased to master.

Closing thoughts

This development pattern has limited use under a narrow set of circumstances. It’s great for experimentation if not stability. So far, I’ve found it plays nicely with tools designed for the typical pre-merge workflow.