Guide for Version Control with Ignition

We are doing a repo per site that depends on a submodule based around our base library project.

This has worked very well so far given our sites are not connected to internet, so we have to move bundle files for changes from dev.

Hi Hunter,

The simplest and most successful approach I've had is using a monorepo with trunk-based development.

Looking at your diagram, I would be cautious about creating long-lived branches for each gateway. I generally view gateways as deployment boundaries rather than development boundaries. The code should be developed once, integrated/merged once, and then deployed to many gateways. Your current approach requires cherry picking or multiple redundant merges.

I prefer:

  • One shared codebase
  • One source of truth (trunk)
  • Short lived feature branches or commit straight to trunk
  • Configuration driven application (tags, connections, custom JSON config, etc.)
  • Independent deployments per gateway

This keeps feature development, bug fixes, and refactoring centralized while still allowing each gateway to have specific site behavior. It also avoids branch drift and the overhead of maintaining multiple long lived branches.

The main caveat is that a monorepo and trunk-based development require a strong CI/CD pipeline. Unit tests, functional tests, and automated validation should run on every commit to catch cross-cutting regressions before deployment.

For Ignition specifically, I would strongly recommend minimizing the number of projects and driving behavior through configuration whenever possible. I've written about that previously here:

I would push for a single project and drive your application entirely on configuration. Project inheritance for me has always been a headache (multiple designers, delayed updates, etc) and is the last tool I reach for.

For gateway configuration I use deployment modes per gateway rather than per environment. This allows me to make configuration changes across all gateways atomically in a single commit.

So far this approach has scaled well for us across multiple sites and gateways.

I hope this is clear and I'm more than happy to go into detail!

Thanks very much for the thoughtful response and references.

In a current use-case of my own, single trunk/project architecture seems a non-starter (at first glance anyway)

assume ~15 projects (for legitimately different use-cases), each with ~5 variations (for site-specific variations perhaps), across ~10 gateways (each with environment-specific deployment modes/tags/project collections)

perhaps it might be helpful to note that the branching strategies in the diagram are purposefully environment/gateway-based (as opposed to feature/release/etc)

I'd appreciate any commentary you might have - here's mine:

while all deployment modes (which include tags) can of course be delivered to all gateways (which i assume would be the case in a trunk-based monorepo, barring strong CD as you mentioned), there's a potential TON of overhead/useless stuff per gateway. I believe it would be difficult to merge between modes if necessary from a development perspective

Smaller project variations (the a/b branches in diagram) could certainly be consolidated and become configuration driven, but again, in the case of legitimately different projects, there's a TON of overhead if all projects exists across all gateways

there's also the consideration in the back of my mind that if a developer just wants to work on ONE project, it's nice to be able to just clone the project repo, instead of the whole gateway.

perhaps you have already solved this 'overhead removal' problem? admittedly it does seem ideal to develop in a monorepo.

@brandon1 i like your submodule idea - where instead of pushing a group of related commits per environment, I could just have a repo with per-environment branches, each submoduling-in the desired state as a grouping of commits, then it's just one push/clone per gateway data dir, instead of several clones across config and projects dirs

edit - i look forward to deployment modes having some control over project state (enable/disable at least)

I do not want to confuse TBD or monorepo with my own opinions about how Ignition should be structured. You can absolutely still use trunk-based development and a monorepo without a single project or my take on deployment modes. The Ignition version control guide actually shows a monorepo structure:

repository/

├── services/
│   ├── gateway-01/
│   └── gateway-02/

└── shared/
    ├── projects/
    └── common-config/

I would recommend reading the entire document. It covers a lot around repository organization and deployment that we're discussing here.

Like any architecture decision, there's tradeoffs and "it depends".

perhaps it might be helpful to note that the branching strategies in the diagram are purposefully environment/gateway-based (as opposed to feature/release/etc)

If I have to give any commentary, it's that you test this out as soon as possible. I would create a git repo and exercise the workflows you expect to perform. In my experience, long-lived branches become unwieldy pretty quickly. My concern is that a branch is being used to represent a deployment boundary when branches are really intended to represent development boundaries.

there's a potential TON of overhead/useless stuff per gateway. I believe it would be difficult to merge between modes if necessary from a development perspective

From a merge perspective we have not experienced significant issues. Each deployment mode owns it's configuration while the core configuration needs to be managed vigilantly.

Smaller project variations (the a/b branches in diagram) could certainly be consolidated and become configuration driven, but again, in the case of legitimately different projects, there's a TON of overhead if all projects exists across all gateways

The question becomes whether the operational and maintenance cost of carrying that unused code and configuration is greater than the cost of maintaining multiple diverging codebases. Different businesses will arrive at different answers.

For our use case, the ability to open one project, make a change once, test it once, and deploy it consistently has been worth that tradeoff.

Thanks for the reply!

this appears to be the crux of the issue:

absent a method to distribute pieces of a Monorepo branch to respective environments, the alternative might be simply cloning ONLY the desired pieces to the respecitve environments via Multi-repo "deployment boundary" repos/branches

as you said (emhasis mine):

any thoughts in the middle? (Portainer GitOps updates?)

FWIW I'm calling the Multi-repo POC i've developed KISSOps

and I suppose it could easily become a development boundary "Monorepo" with submodules....

would be interesting to know if IA still uses the the per-vertical "development" multi-repo > public demo "production" monorepo flow discussed in this presentation (for 8.3)