Git for Architecture Models: Where It Stops Working

Git is a real improvement

Moving Archi models into Git — usually with coArchi — is a genuine step up from files on a share. You get history with authors and messages, branches, a review mechanism, and a backup that someone else maintains. For a small team of technically comfortable architects it works, and it costs nothing.

This article is not an argument against it. It is an argument about where its boundary is, because teams tend to discover that boundary during an incident rather than in advance.

Git versions the file, not the model

The core issue is a mismatch of granularity. Git tracks changes to lines in a text file. An architecture model is a graph — elements, relationships, diagram objects — that happens to be serialised into a file. The serialisation is an implementation detail, and it is not stable in the way Git's merge algorithm assumes.

Figure 1: Where the abstraction leaks
Figure 1: Where the abstraction leaks

Two architects making unrelated changes in different parts of the model can still produce a conflict, because the tool wrote their changes to nearby regions of the same file. And when a conflict does occur, the thing a human has to resolve is XML they did not write and cannot meaningfully read.

Where coArchi's seams actually run

coArchi improves on the naive one-big-file picture, and the improvement is worth describing precisely because it defines where the remaining pain lives. Instead of one monolithic .archimate file, the plugin persists the model as many small XML fragments — folders and elements as separate files under a model repository directory. Two architects editing genuinely different elements therefore touch different files, and Git merges their work without ceremony. For a well-partitioned model with disciplined architects, weeks can pass without a conflict, which is exactly the experience that convinces teams the problem is solved.

The seams show at the operations that cross fragments. Moving elements between folders rewrites both folder files and can surface as a delete-versus-modify conflict when someone else touched either. Relationship changes land in fragments the architect never consciously chose, so "unrelated" edits collide more often than the mental model predicts. Diagram edits concentrate into the diagram's own fragment — two people improving the same view produce a conflict in which every line is geometry, and the only honest resolutions are "mine" or "theirs". And the model's index of fragments is itself shared state; when it conflicts, the repository is wrong about what exists until someone resolves XML by hand. None of this is coArchi doing a poor job — it is the file-granularity ceiling being reached from below. The fragments make the easy cases automatic; they cannot make the hard cases meaningful, because the hard cases were never textual to begin with.

What a bad merge actually costs

The failure mode worth understanding is not the conflict you notice. It is the merge that succeeds and should not have.

Git will happily combine two changes that are textually compatible and semantically incoherent — a relationship whose source element was deleted in the other branch, a diagram object referencing an element that no longer exists. The file parses. Archi opens it. The model is subtly wrong, and nobody finds out until something downstream breaks.

This is the strongest argument for model-aware concurrency control. A merge that produces broken references is worse than a rejected publish, because the rejected publish tells you.

The things Git was never going to give you

Beyond merging, several requirements simply sit outside what a version control system does:

  • Scoped access. Git permissions are per repository. Giving a team access to one project without the rest usually means splitting the model across repositories, which reintroduces the cross-model relationship problem.
  • Search across models. There is no index. Finding every application that touches customer data means cloning and grepping XML.
  • Audit. A commit log is a good record until someone force-pushes. History that can be rewritten is not audit evidence.
  • Non-technical access. Asking a risk officer to clone a repository is not a plan.

Where Git remains the right answer

It is worth being even-handed. Git is the better choice when:

  • the team is small, technical, and already lives in Git;
  • models are modest in size and rarely edited concurrently;
  • architecture is a developer-adjacent activity rather than a governed enterprise function;
  • you need branching for genuine parallel exploration, which a lock-based repository deliberately does not offer.

That last point is a real trade-off and not a small one. A lock-and-publish model prevents the mess, and it also prevents speculative parallel work. If your practice depends on exploring three alternative target architectures simultaneously, that is a cost you should weigh rather than dismiss.

Branching that does not lie to you

Branches are Git's genuine gift to architecture work — the ability to model a target state without touching the shared current state is something lock-based repositories struggle to offer. The craft is using them in a way that does not write cheques the merge cannot cash.

The discipline that works: exploration branches are short-lived, single-owner, and merged by re-application rather than by algorithm. When the alternative target architecture wins the argument, its author re-applies the decisions to the main branch as fresh, coherent edits — with the branch open in a second window as the reference — rather than asking Git to interleave six weeks of divergence automatically. This sounds like waste and is the opposite: the re-application takes an afternoon, produces a clean semantic change with a clean message, and skips the day of conflict archaeology that the automatic merge was going to become. The branch's job was to hold the thinking, not to be mechanically mergeable, and once that is accepted, branches stop being dangerous.

Tags deserve the same reframing. A tag on the commit that went to the review board is the closest thing this workflow has to a baseline in the governance sense — cheap, immutable in practice if history is never rewritten, and infinitely better than the model_final_v3_REVIEWED.archimate files it replaces. Tag deliberately: at decisions, not at Fridays. A repository whose tags map one-to-one onto governance moments can answer "what did the board approve in June" in one checkout, which is most of what teams that later migrate to a real repository will wish they had recorded all along.

The repository deserves a CI pipeline too

Teams that keep models in Git almost never give them what they give every other repository: a pipeline that checks the pushes. Yet this is where Git's ecosystem genuinely compensates for its semantic blindness, because the checks that Git cannot do at merge time can run two minutes after, on the merged result.

A model CI job is not exotic. Archi runs headless from the command line, and a jArchi script can load the model, walk it, and fail the build on exactly the defects a bad merge produces — relationships with missing endpoints, diagram objects referencing deleted elements, duplicate identifiers from a botched resolution. That is the publication gate, moved to the commit, where the person who caused the finding is still the person looking at the screen. Add an HTML export as a build artefact and every push produces a browsable preview, which quietly solves half of the non-technical-access complaint as well.

The bad merge that "succeeds and should not have" — the central hazard of this whole workflow — is exactly the defect this pipeline catches on the next push, turning a silent corruption into a red build with a named commit. It does not make merging semantic; nothing does. But a Git workflow with model validation in CI is a different risk proposition from the same workflow without it, and the cost is a script and a runner the team already knows how to operate.

The migration question

Teams that do move off Git usually want to keep the history, and this is the point to be realistic: the Git history is a history of files. Converting it into a meaningful model history is largely not possible, because the intermediate states were never model states anyone approved.

The pragmatic approach is to migrate the current state, record where each model came from — repository, path, commit SHA — and keep the Git repository read-only as an archive. New history starts clean, in a form that can actually be queried. Pretending you can carry the old history forward tends to produce something that satisfies nobody.

Two estates, two right answers

Abstract trade-offs land better as stories, so here are two, lightly disguised from real engagements.

The first is a four-person architecture guild inside a product company. All four write code in their other job; the models cover one product family; branches carry genuine what-if work that gets debated in pull requests, imperfect diffs and all. They tag the commit before each quarterly review, run a jArchi validation in CI, and publish an HTML export to an internal bucket on every merge. They have been running this way for three years, have resolved perhaps a dozen awkward conflicts in that time, and would lose real capability — the branching, the review habit, the zero infrastructure — by migrating anywhere. Git is not their compromise; it is their correct answer, and the checklist above says so on every line.

The second is a bank whose architecture function grew from two people to eleven in eighteen months, on a Git estate that had been fine at two. The signals arrived on schedule: an architect quietly keeping a private working copy because integration days were painful; a risk department that needed reading access and could not be given a Git client; then the audit question about March. Nobody had done anything wrong — the workflow had simply been outgrown, and the force of the realisation was that no amount of discipline would buy back the missing rows: scoped access, immutable history, non-technical readers. They took the half-step first, migrated the estate the following year, and kept the Git repository read-only as the archive it had honestly become.

Same tooling, opposite conclusions, both correct. The variable was never Git's quality; it was which rows of the scorecard the organisation was actually being asked to answer for.

Making Git work as well as it can

If Git is your answer for now, several practices materially reduce the pain and none of them requires new tooling.

  1. Commit small and often. Large commits spanning many elements produce conflicts that are impossible to reason about. A commit per coherent change is resolvable.
  2. Pull before you open the model, not before you commit. The expensive conflict is the one discovered after three hours of editing.
  3. Agree a de facto lock anyway. Most Git-based Archi teams end up with a social locking convention because merging is unpleasant. Making it explicit is better than each person inventing it.
  4. Never rewrite history. Force-pushing a shared architecture branch destroys the one property that made Git worth adopting.

The half-step: keep Git for editing, publish for everyone else

Between "stay on Git" and "migrate to a repository platform" sits an option that deserves more attention than it gets, because it addresses the two loudest complaints without touching the editing workflow at all: keep Git as the architects' working surface, and generate a read-only portal from the main branch for everyone who is not an architect.

This is the same publication machinery any repository would feed — extraction, generation, a static site — pointed at a Git checkout instead of a database. The risk officer gets a browsable, searchable portal instead of a clone; the "search across models" complaint dissolves into a search index; and the architects keep the branching workflow they chose Git for in the first place. Run it from the CI pipeline described above and the portal updates on every merge to main, which makes the main branch mean something: it is no longer just the default branch, it is the published architecture, with all the gate-keeping instincts that phrase should trigger.

What the half-step does not fix is the audit gap — history that can be rewritten remains history that cannot be evidence, and scoped access remains repository-granularity. Teams on a governance trajectory usually take the half-step first and the full migration later, and the half-step makes the migration easier rather than harder: the publication pipeline, the gate rules and the readers all survive the move unchanged, because they only ever depended on the snapshot, not on where it came from.

An honest scorecard

Laid side by side, the trade resolves into a table most teams can locate themselves in within a minute:

RequirementGit + coArchiRepository platform
History with authorsYes, file-grainedYes, model-grained
Parallel explorationBranches, genuinely goodLimited by design
Safe concurrent editingUntil the seamsLeases and revision checks
Scoped accessPer repository onlyPer model and project
Search across the estateNoIndexed
Audit-grade historyNo — rewritableImmutable revisions
Non-technical readersVia generated portal onlyNative, plus portal
Cost and setupNearly freeReal

Neither column wins every row, which is the point. The mistake this article exists to prevent is not choosing Git — it is choosing Git for the rows where it says no, discovering that during an audit or after a bad merge, and calling the result a tooling failure. Read the left column honestly, take the half-step when its rows start to pinch, and treat the first force-push, the first locked-out stakeholder or the first unanswerable audit question as what they are: the boundary, announcing itself politely before it does so expensively.

The signals that you have outgrown it

Three specific ones, in the order they usually appear:

Someone starts avoiding the model. An architect who batches up changes because integrating is painful is telling you the workflow costs more than the work. This shows up as models that are always slightly out of date rather than as complaints.

A non-developer needs access. The moment a risk officer or a business analyst needs to read the architecture, Git stops being a collaboration mechanism and becomes a barrier.

An audit question arrives. "Who could have changed this in March" is answerable from a Git repository only if nobody rewrote history and permissions were never changed — neither of which you can demonstrate.