Logo niceshops

niceshops

Established Company

Unser Weg zum Monorepo

Description

Lena Höhsl und Sebastian Mandl von niceshops sprechen in ihrem devjobs.at TechTalk darüber, wie das Devteam im Unternehmen eine einheitliche Struktur in viele kleine Teilprojekte gebracht hat.

By playing the video, you agree to data transfer to YouTube and acknowledge the privacy policy.

Video Summary

In “Unser Weg zum Monorepo,” Lena Höhsl & Sebastian Mandl (niceshops) describe moving from numerous per‑shop repos with Git‑Flow and Jenkins to a GitLab‑based monorepo using trunk‑based development and MR‑only workflows. They detail a QA pipeline (linting, static analysis, unit tests), code‑ownership approvals, MR labels that drive scoped deployments, YouTrack integration, and a simplified staging model (single code upload, V‑hosts per shop) that cut merge conflicts and complexity while keeping main green. Actionable takeaways include their migration playbook (up‑front analysis, a conversion script, DI refactors, a “day‑X” cutover) and the lesson to ship small, always‑working increments; next up are automated Cypress/Selenium tests and application warming.

From Git-Flow Overhead to a Monorepo: How niceshops Boosted Speed and Quality with Trunk-Based Development

Context: “Unser Weg zum Monorepo” by Lena Höhsl & Sebastian Mandl (niceshops)

At DevJobs.at we watched “Unser Weg zum Monorepo” with Lena Höhsl and Sebastian Mandl (niceshops). While the title points to a repository strategy, the speakers made it clear early on: the monorepo was only the tip of the iceberg. What really happened was a deep overhaul of the development stack—branching strategy, CI/CD, deployment, and developer habits were all reworked to optimize for smaller, safer steps backed by GitLab automation and unambiguous quality gates.

What stood out: this wasn’t treated as a tool migration. It was an organizational shift toward tighter iteration loops, with tooling (GitLab, pipelines, approvals) set up to enforce a consistent, transparent workflow.

Starting Point: Many shops, even more repositories—and little visibility

niceshops operates numerous online stores. Before the change, each shop had its own Git repository. Shared components were pulled in as submodules. Sebastian summarized the prior setup:

  • One repository per shop.
  • Multiple submodules per project:
  • a common library (library source code)
  • central configuration (config)
  • a repository for images
  • a previously separate warehouse module (already integrated earlier)

In practice, this became “totally unclear even for experienced developers.” A cross-cutting change meant checking out shop after shop, applying changes, pushing, and coordinating reviews—time-consuming and error-prone. Each shop had long-running pipelines on top, which slowed feedback even more.

Git-Flow in practice: team branches, feature branches—and escalating merges

Organizationally, niceshops used Git-Flow with three permanent branches: Master, Develop, and Hotfix. On top, teams worked with Sprint-level team branches and feature branches underneath. At the end of a sprint, team branches were merged back into Develop—the moment Sebastian frankly described as when merge conflicts “really, really escalated.”

“…that was usually the point where merge conflicts really, really escalated… because so much progress happened in all teams, but information between teams wasn’t being shared.”

The outcome: high coordination overhead at the worst possible time, late integration, and the risks that come with it. Transparency suffered because changes lived in branches and only surfaced late.

CI as a black box: Jenkins as “curse and blessing”

For CI, niceshops used Jenkins—powerful, but a black box for developers. Sebastian joked it hosted “ten different programming languages.” DevOps knew the tool well, but for developers it boiled down to pressing buttons. Net effect: too little proximity to the pipeline logic and too little feel for the quality of individual steps toward merge.

The turning point: A monorepo and a new collaboration hub (GitLab)

The decision was radical: “We basically threw everything overboard.” A single monorepo replaced the many repos. The previous bare-metal Git server was replaced with GitLab. With it came a fundamental shift in branching and delivery.

Trunk-Based Development over Git-Flow: smaller steps, earlier feedback

The biggest change was branching: away from Git-Flow, toward Trunk-Based Development.

  • The trunk (Main/Master) is the central work branch.
  • All changes branch off trunk as small, short-lived feature branches.
  • Everything returns via Merge Requests (MR) back into trunk.
  • Release branches “stay put”; when a production issue occurs, it’s fixed in Main first and then cherry-picked into the relevant release branch.

This reduces integration risk because changes hit Main sooner, conflicts are smaller, and teams benefit from each other’s work sooner. Sebastian summed it up:

“Changes are much smaller… it’s much easier for reviewers… and there are simply far fewer errors.”

Quality gates in the MR: protected branches, auto-MRs, a QA pipeline, and group approvals

GitLab replaced Jenkins as the center of gravity. niceshops established several mechanisms:

  • No direct pushes to Master: everything goes through Merge Requests.
  • Automatic MR creation: pushing a branch auto-creates a Merge Request.
  • A full QA pipeline on the MR:
  • PHPStan and linting
  • unit tests
  • Group-based approvals tied to code areas: relevant parts of the codebase are owned by groups whose approvals are required in MRs.

The result is a consistent quality workflow. Main stays “almost always green,” because the pipeline is the admission ticket and changes are small:

“…we no longer have that one merge day with a giant merge conflict… it’s always these smaller changes merging back in.”

Rethinking deployments: Jenkins out, GitLab in—and simpler staging via V-Hosts

With Jenkins gone, deployment was rewritten in GitLab.

  • Live deployments remain largely similar to before.
  • Staging got dramatically simpler with the monorepo: the full source is deployed once, and individual shops (A, B, …) are selected via Virtual Hosts.

A particularly neat detail: MR labels drive the pipeline. On push, labels are assigned automatically based on what changed. Additionally, YouTrack information is attached to the MR via a custom integration. Seeing ticket context directly inside the MR means “one system” to work in instead of juggling multiple tools.

Preparation: two months of analysis, a script in nine iterations, pipeline design, and DI refactors

The migration was carefully prepared:

  • Two months of analysis to map what’s necessary and how to execute it.
  • A colleague wrote a migration script—nine iterations were needed “until everything was really where it was supposed to be,” reflecting the complexity of the prior project structure.
  • DevOps developed GitLab pipelines in parallel: creating MRs, driving deployments, and wiring QA stages.
  • Development teams handled targeted tasks: breaking up application classes and replacing them with dependency injection. The goal was to reduce hard-wired, shop-specific instantiation and eliminate the “ping-pong” between application and library layers.

The cutover: one sprint, tabula rasa, two weeks on thaw

niceshops reserved an entire sprint across three Scrum teams for the switchover. On “Day X” it was “tabula rasa”: everything was copied into the new repository; the old world was frozen. For two weeks they kept a thawing phase to enable emergency deploys from the old system if bugs surfaced in production. After that, the focus shifted to getting the QA pipeline fully operational and ironing out minor issues in the new setup.

Sebastian’s pragmatic verdict: any work not finished by Day X was “lost lifetime,” because pulling pieces over from the old world into the monorepo later was cumbersome. That underlines the value of a hard cutover and a disciplined scope.

Why it’s worth it: immediate, tangible improvements

After a few months of running the new setup, the verdict is positive:

  • Higher software quality: thanks to smaller changes, earlier integration, and automated quality gates.
  • Faster reviews: smaller MR diffs are easier to reason about.
  • A consistently green Main: no more “merge day” infernos.
  • Immediate cross-team benefit: “The entire team benefits immediately from a change that goes back into Main—so all teams benefit immediately.”

One underappreciated effect: unconscious co-testing. If you merge a change to the checkout flow on day one of the sprint, everyone touching that flow during the sprint implicitly exercises your change because it’s in Main.

Architectural win: ending code “ping-pong”

Previously, there was a “ping-pong” between the application layer (shop-specific classes) and the library: one instantiated the other, overrides lived at the shop level, the library called back again. With dependency injection, this coupling was reduced. The outcome: fewer files, clearer boundaries, fewer side effects driven by tight coupling.

Lessons learned: people, habits, cadence

The tech migration was just part of the challenge. The core shift was behavioral:

  • Get everyone on board: “Bringing everyone along from the start and showing them how the way of working will be” was the biggest hurdle.
  • Change the working style: from “big projects” to “small bites.” Each step heading for trunk “must always be fully working”—no half-integrated states that only snap together later.
  • Coordinate Day X: The hard cut across three Scrum teams meant unfinished work couldn’t easily be pulled over. The pressure to meet the new cadence was real, but it drives healthier planning and smaller scopes.

What’s next: more automation in the pipeline and application warming

The journey continues with two major lines of improvement:

  • Automated end-to-end testing: The QA department is translating manual checks into automated Cypress or Selenium tests. By attaching labels to MRs, these tests will be triggered conditionally and run “fully automatically to click through the complete frontend, and backend processes as well” in the pipeline.
  • Application warming at deploy time: Pre-generating configurations and cache files during deployment so the first request after a deploy doesn’t have to build caches. The target is a faster, more stable live system immediately after rollout.

Practical takeaways for teams with similar pains

While every setup is different, the patterns from “Unser Weg zum Monorepo” by Lena Höhsl & Sebastian Mandl (niceshops) are broadly applicable:

  1. Prefer transparency over fragmented complexity: Many repos with submodules can erode visibility. A monorepo lowers integration costs—if disciplined quality gates exist.
  2. Trunk-Based Development enforces good hygiene: small branches, fast merges, continuous QA, instead of infrequent, conflict-heavy integrations.
  3. Make MRs the center of quality: protected branches, auto-created MRs, static analysis, unit tests, and group approvals keep trunk green.
  4. Consolidate deployment: deploy once, route via V-Hosts, and drive relevant pipeline paths via labels.
  5. Don’t let CI be a black box: developers need to read, understand, and influence the quality pipeline. GitLab as a single, visible hub helps.
  6. Prepare thoroughly: analysis, a migration script (with iterations!), a parallel-built pipeline stack, and targeted refactors like DI pave the way.
  7. Plan for a hard cut: a defined Day X prevents the old and new worlds from lingering—but it demands cross-team discipline and scope clarity.
  8. Integrate early, let the organization co-test: merging at the start of the sprint spreads test coverage organically.
  9. Clean up architecture: where layers “ping-pong,” dependency injection and clear ownership reduce coupling.
  10. Keep automating: end-to-end tests and application warming close the gap between pipeline success and perceived product quality post-deploy.

Conclusion: The monorepo as catalyst—cadence is the real change

“Unser Weg zum Monorepo” with Lena Höhsl & Sebastian Mandl (niceshops) shows how switching to Trunk-Based Development on GitLab can both accelerate delivery and raise quality. The monorepo was the vehicle; the real gains came from small, clean changes, an almost always green Main, and strict, automated quality gates. The most compelling details are practical ones: auto-created MRs, label-driven pipelines, YouTrack context in MRs, and DI to eliminate code ping-pong.

If you’re wrestling with Git-Flow fatigue, merge pile-ups, and opaque pipelines, this session outlines a clear path: simplify decisively, shift feedback forward, make integration a daily habit—and bring both your organization and your codebase into a calmer, more predictable cadence.

More information from the session: www.unser-weg-zum-monorepo.com

More Tech Lead Stories