• Concept
  • Version · 6.0
  • Create

Choose a branching strategy

Last updated: September 29, 2026

Set up your changelog structure decides where a changelog file lives. This page decides when the changes in it reach an environment. That is where implementations with more than two developers actually break.

Get this wrong and you get one of two failures: changesets deployed to production from a branch nobody meant to release, or two developers editing the same changelog in parallel and discovering it at merge time, after both have tested locally.

Pick a branching model

Two models cover almost every implementation. Pick the one that matches how you already release. Do not adopt a new branching model and Liquibase in the same quarter.

Trunk-based

Developers work on short-lived branches and merge small changes frequently into one main branch. Environments map to pipeline stages, not to branches: the same commit is promoted from dev to QA to production.

Best when you deploy continuously and want the shortest path from merge to deployed. Fewer long-lived branches means dramatically fewer changelog merge conflicts, because two branches rarely live long enough to diverge.

Gitflow

Long-lived branches, commonly main, develop, and qa, usually mapped to environments, plus short-lived feature branches. Changes are promoted by merging between branches.

Best when releases are batched and each environment has an approval gate. More merge overhead, and more opportunity for changelog conflicts, in exchange for explicit control over what reaches production and when.

How each handles the awkward cases

Situation

Trunk-based

Gitflow

Urgent production fix

Merge to main, promote straight through

Hotfix branch off main, merge back to main and develop, forgetting the second is a classic source of regressions

Batched release

Use contexts or labels to gate what applies

Natural: merge develop > qa > main

Two developers, same table

Rare; branches are short

Common; needs the file conventions below

A change that must not ship yet

Contexts, or don't merge

Hold it on the feature branch

Avoid changelog merge conflicts

Independent of branching model, three conventions prevent most conflicts:

One changeset per file, referenced from a parent changelog. If every developer appends to a single changelog.sql, every concurrent change is a conflict on the same lines. Small files referenced from a parent make concurrent work merge cleanly.

Never renumber, reorder, or edit a deployed changeset. Liquibase tracks changesets by a checksum of their contents. Editing one that has already run causes a validation failure on the next update. And "fixing" it by clearing the checksum hides a real difference between what you think is deployed and what is. Add a new changeset instead.

Choose `includeAll` or `include` deliberately. includeAll on a directory means new files are picked up automatically without touching the parent. Fewer merge conflicts, but the execution order is alphabetical and you must not depend on it mattering. Explicit include lists give you exact ordering at the cost of a shared file every change touches. Use includeAll where order is irrelevant (independent objects) and include where it isn't (anything with dependencies).

Set merge rules

Require pull requests to shared branches. This is where the review that used to be a DBA ticket now happens, and where it's cheapest.

Run changelog-scoped policy checks as a branch-protection check. A violation should block the merge, not the deployment. Changelog-scoped checks need no database connection, so they run in seconds on any runner and give the developer feedback while they still have the change in their head.

Database-scoped checks generally cannot be a merge gate. They need a live connection to evaluate objects in a database, which a pull request doesn't have. Run those post-deployment or on a schedule. This distinction trips up almost every implementation once. See Policy check roll out best practices.

Centralise shared assets

Flow files and check-settings files belong in one repository, with read-only access for application teams. If every team keeps its own copy, every team's governance drifts, and the standard you agreed becomes six standards nobody can audit.

The practical arrangement: a platform or DBA team owns the governance repo and takes pull requests against it; application repos reference the flows rather than copying them.