git workflows for open-core businesses: a new perspective
the open-core git workflow that holds up is trunk-based development on the public repo, a thin private package for genuinely proprietary modules, and per-tier flag config as the packaging layer. branches stay short-lived and feature-scoped; nothing about your pricing model lives in git topology.
rethinking what git is for
git answers 'what changed, when, by whom'. open-core businesses keep asking it a second question — 'who is this feature for?' — and encoding the answer in branches. the new perspective is a clean separation of concerns: git owns history, a config layer owns packaging, and the two never compete. once you see edition branches as a category error, the rest of the workflow follows.
the day-to-day loop
the working agreement fits on an index card:
- all work happens in short-lived feature branches off the public main; nothing lives unmerged past a few days.
- paid features merge to main behind a flag, defaulted off — code review happens in public, where your contributors are.
- the rare proprietary module lives in a private package main imports optionally; its activation is still a flag.
- per-tier flag config (tiers.json) is committed and reviewed like code; flipping saas-on for a feature is a one-line pr.
- ci builds every tier from every main commit, so 'does the community edition still build?' is never a question.
what changes for contributors and for the business
contributors get the real codebase, including the honest shape of paid gates — a flag check reads as a fact, not a betrayal. maintainers stop maintaining a shadow edition. and the business gains an artifact most open-core companies lack: a single reviewable file that states, for every tier, exactly what's enabled. that file answers due-diligence questions, support escalations, and roadmap debates alike.
companies that have walked the opposite road validate the direction: gitlab merged its community and enterprise codebases back together after years apart, citing development drag. starting unified is cheaper than re-unifying.
where tier·dev sits in the workflow
tier·dev is the packaging layer's ui: connect the repo, define tiers, manage flags with descriptions and per-tier values, and generate the config file your ci consumes. git stays pure history; the matrix stays the single answer to 'who gets what'.
see this on your own repo
tier·dev turns the open-source / saas difference into per-tier feature flags — one repo, generated config, no sdk.
faq
- should the private package be a submodule or a registry dependency?
- a registry dependency (private npm/pypi/etc.) ages better than a submodule — versioned, cacheable, and invisible to open-source builds that don't request it.
- how do we review paid features 'in public' without leaking roadmap?
- merge dark with neutral naming, and keep marketing-sensitive copy in the private package or behind launch-day config. the code being visible early is usually a non-event in practice.
- does trunk-based development require feature flags?
- effectively yes for anything unfinished or edition-specific — flags are what make merging early safe. tier flags are the same mechanism pointed at packaging.