Apr 22, 2025·7 min read

Trunk-based development vs GitFlow for weekly shipping

Trunk-based development vs GitFlow for weekly shipping: compare merge friction, release predictability, hotfixes, and stable QA setups.

Trunk-based development vs GitFlow for weekly shipping

Why weekly shipping gets messy with the wrong branching model

Weekly shipping sounds simple until the week you miss it. The build is "almost ready" on Thursday, QA finds issues late Friday, and Monday turns into cleanup instead of a clean start.

A major driver is your branching model. It decides when changes meet, where integration happens, and how quickly you can recover when something breaks. If integration is pushed to the end of the week, you pay for it with merge conflicts, surprise bugs, and shaky test environments.

When the workflow is working against you, it usually feels like this:

  • Merges take longer than the feature work that caused them.
  • QA tests the wrong mix of changes because branches drift.
  • Releases become a negotiation instead of a routine.
  • Hotfixes trigger panic because nobody is sure what else will ship.
  • People stop trusting QA and start asking for exceptions.

Branching also shapes QA stability. If QA keeps bouncing between half-integrated code paths, it becomes a moving target. Even strong testers can't give clear answers when the system under test changes every few hours, or a late merge quietly replaces what they tested yesterday.

That’s why teams end up comparing trunk-based development and GitFlow when they move to a weekly release rhythm. The useful question isn't which one is popular. It's which one reduces merge pain, keeps releases predictable, makes hotfixes safe and fast, and keeps QA meaningful.

Assume a small to mid-size team, one shared repo, CI running on every push. Maybe you ship a web app and an API. Or maybe part of the team builds visually in a platform like AppMaster while still managing generated code and deployments like any other product team.

If your current process creates big, end-of-week merges, your weekly cadence will keep slipping. If it encourages small, frequent integration, weekly releases start to feel boring (in the best way).

Trunk-based development and GitFlow in plain language

Both approaches are just rules for how you use branches so work can go from "in progress" to "released" without chaos. The real difference is how many long-lived branches you keep, and how long work stays separate before it meets everyone else’s code.

  • Trunk-based keeps almost everything close to main.
  • GitFlow keeps separate lanes for ongoing work and release stabilization.

Trunk-based development (plain terms)

Trunk-based development treats main (the trunk) as the center. People work in short-lived branches (hours to a day or two), merge back frequently, and keep main in a releasable state.

If something isn't ready, you either keep it small enough to finish quickly, or you hide it behind a feature flag so it can ship safely without being visible.

GitFlow (plain terms)

GitFlow typically uses a long-lived develop branch where feature work lands first, plus feature branches off develop. Near release time, you cut a release/* branch to stabilize and test. If production breaks, you cut a hotfix/* branch (often from main) and merge it back.

This model optimizes for separation: ongoing work can continue on develop while the release branch is being tested and patched.

A lot of pain comes from common misunderstandings:

  • Treating trunk-based as "no branches" (it still uses branches, they’re just short-lived).
  • Using GitFlow but never creating a real release branch, so develop becomes an unstable staging area.
  • Letting feature branches live for weeks, which turns any model into merge trouble.
  • Confusing "releasable" with "everything is finished" instead of "safe to deploy."

Merge friction: what actually causes it

Merge conflicts usually come from two sources: branches that live too long, and multiple people changing the same areas without coordination.

The biggest practical difference between trunk-based and GitFlow is how long work stays apart before it meets other work.

With trunk-based development, changes hit the main line often. Pull requests are smaller, diffs are smaller, and conflicts show up earlier while the context is still fresh. Conflicts still happen, but they’re usually easier to resolve because you’re reconciling a few lines, not two weeks of drift. The tradeoff is discipline: keep builds green, keep changes incremental, and treat main like the product.

With GitFlow, feature work can sit longer without affecting other developers day to day. The cost shows up later as larger merge events: feature into develop, develop into release/*, and release/* into main. Each merge is a bigger meeting of changes, so conflicts are more likely and harder to untangle. For weekly shipping, those big merges tend to land right when the team wants to be testing.

Code review load shifts too. Trunk-based usually means more reviews, but each one is quicker to understand. GitFlow often means fewer, heavier reviews, plus extra review time during release merges when everyone is tired.

To reduce merge friction in either model:

  • Keep PRs small and focused (one goal at a time).
  • Agree on ownership for risky areas (migrations, shared config, core UI).
  • Pull in upstream changes daily so you don’t drift.
  • If a file is constantly "hot," pair on it instead of racing in parallel.

If conflicts feel constant, it’s usually a sign you’re integrating too late, not that Git is the problem.

Release predictability for a weekly cadence

Predictability means three things: you know when the release goes out, you know what’s in it, and you know what checks must pass before it ships. Teams usually miss weekly releases because they mix scope decisions with last-minute fixing.

In trunk-based development, weekly releases stay predictable when main stays green. You merge small changes often and control scope with feature flags instead of long-lived branches. That keeps the weekly train moving even if a feature isn't finished. The code can land, but the user-facing behavior stays off until it’s ready.

Quality gates are often simpler because there’s one place to validate:

  • Automated tests must pass on main.
  • QA tests a stable candidate build, not whatever landed last hour.
  • Rollout and rollback steps are written down.
  • There’s a clear release cutoff time (even if commits keep landing).

In GitFlow, predictability comes from the release branch acting like a freeze zone. You pick a cutoff, create release/*, and only allow changes needed to ship. That boundary helps, but it adds coordination because fixes usually need to be applied in more than one place (release and develop).

Unfinished work is handled differently:

  • Trunk-based: merge safe pieces and keep the rest behind flags.
  • GitFlow: keep unfinished work in develop and exclude it from the release branch.

Example: if checkout improvements are half done by Wednesday, trunk-based can merge the safe refactors and keep the new UI hidden. GitFlow usually keeps it in develop, ships without it, and finishes it for the next weekly release.

Hotfix flow: the fastest safe path to production

Deliver internal tools faster
Create internal tools and admin panels that match weekly shipping, without weeks of integration pain.
Build Now

A hotfix isn’t normal work. It needs speed, low risk, and a path that brings the change back to where the team is working so you don’t fix the same bug twice.

Start with one question: what exact code is running in production right now? If you can’t answer that in seconds, hotfixes turn into guesswork.

Hotfixes with trunk-based development

Trunk-based hotfixes can feel simpler because main is treated as the source of truth.

A common flow:

  • Create a short-lived branch from the production commit (often main).
  • Make the smallest possible fix (add a test if you can).
  • Merge back to main quickly.
  • Deploy from main and tag the release.

Because the team integrates into main frequently, the hotfix naturally becomes part of the next weekly release. The main risk is breaking the "main is releasable" rule by letting half-done work sit in main. Feature flags help, but keep them off by default and verify the hotfix without enabling unrelated features.

Hotfixes with GitFlow

In GitFlow, hotfixes usually start from main (production), then must be merged back into develop so the fix isn't lost.

A safe flow:

  • Branch hotfix/* from main at the production tag.
  • Fix and release (either from the hotfix branch or after merging into main).
  • Merge the hotfix into main and also into develop.
  • If a release/* branch exists, merge into that too.

The most common failure is forgetting one of those merges. A week later, the bug "returns" because develop never got the patch.

A simple rule prevents most of this: a hotfix isn’t done until it’s merged into every long-lived branch that will ship again.

How to keep QA environments stable (without blocking the team)

Weekly shipping falls apart when "QA" means "whatever is deployed right now." Name your environments and give each one a job: dev for fast feedback, QA for team testing, staging for release checks, prod for customers. If you can’t explain an environment’s purpose in one sentence, people will use it incorrectly.

Rules that prevent moving targets

Stable QA is less about your branching model and more about what you deploy.

In trunk-based work, don’t deploy random commits to QA. Deploy a pinned candidate (tagged build, build number, or a short-lived release-candidate branch) that passes the same checks every time. QA gets something fixed to test, even while development continues on main.

In GitFlow, QA usually tracks the release branch. The trap is letting the release branch keep changing after QA starts. Once QA begins, treat the release branch like a contract: only accept approved fixes, and only through a clear process.

A small set of rules keeps either approach predictable:

  • Deploy to QA only from passing builds.
  • Pin the deployed version (tag, build number, or release branch head) and announce it.
  • Limit QA changes to bug fixes, not new features.
  • Reset test data on a schedule and document what gets wiped.
  • Keep configuration as code (variables and templates) to reduce environment drift.

If your team uses AppMaster for part of the build, keep the same principle: regenerate and deploy a specific build for QA, not a constantly changing set of edits.

When multiple teams share QA

One shared QA environment becomes a bottleneck when two teams need different versions. If you can’t afford separate QA environments, add a lightweight reservation rule: one team owns QA for a time window, and everyone else uses dev or staging. Feature flags also help because unfinished work can be deployed without being visible to testers.

Example: Team A is validating the weekly release candidate, so QA stays pinned to build 1842 until sign-off. Team B can keep merging fixes, but those changes wait for the next candidate instead of shifting what QA is testing mid-cycle.

Step-by-step: choose a workflow your team can follow every week

Run a weekly shipping pilot
Build a weekly-release pilot and see how smaller merges and stable QA feel in practice.
Try AppMaster

Write down what "weekly shipping" means for you. Pick a release day and time, decide what level of risk is acceptable (for example, "no known P1 bugs"), and note team size and time zones. This keeps branch debates from turning into priority arguments.

Pick one base model and commit to it for a month. Don’t mix models on day one. Mixing usually adds rules without reducing surprises.

A simple weekly workflow you can adapt:

  • Keep branch lifetimes short (hours to 1-2 days) and merge at least daily.
  • Add safety rails: fast CI, a short required review, and a small set of automated tests that catch real breakages.
  • Decide how you control scope: feature flags, a short-lived release branch near the end of the week, or tags for the exact release commit.
  • Define hotfix steps: who can trigger one, what checks are required, and how the fix gets back into the main line.
  • Keep QA stable: decide what QA tracks (release branch or pinned candidate) and don’t change it mid-test unless you restart the test cycle.

Write the minimum workflow on one page. It should be short enough that a new teammate can follow it without a meeting. This matters even more if part of the team works visually (for example, in AppMaster) and part works in code, because handoffs fail when rules live only in someone’s head.

Example: a realistic weekly release in both models

Make releases predictable
Set up a simple promotion flow from QA to production and stop shipping surprises.
Start Now

Picture a 6-person product team that ships every Friday. Two QA testers share one staging environment, so if staging is unstable, testing stops for everyone.

A busy week with GitFlow

Monday: three developers finish features and open pull requests into develop. QA starts testing staging built from develop.

Wednesday: the team cuts release/1.8 to protect Friday’s shipment. New work keeps landing in develop, but QA now focuses on the release build.

Thursday afternoon: a late bug shows up. The fix lands in release/1.8 first so QA can retest quickly. Then someone merges that fix back into develop, which is where mistakes often happen.

A typical rhythm:

  • Mon-Tue: features merge into develop, staging changes often.
  • Wed: create release/1.8, staging switches to release builds.
  • Thu: bug fix in release/1.8, then merge back to develop.
  • Fri: merge release/1.8 into main, tag and deploy.

The same week with trunk-based development

The week is shaped around small, frequent merges into main. Features ship behind flags so incomplete work can be merged without affecting users.

Monday to Thursday: developers merge small changes daily. QA tests a pinned candidate build.

Tuesday: a production issue appears. The hotfix is a short branch off main, merged back immediately after review, then promoted to production. Because main is the source of truth, there’s no extra back-merge step.

Either way, the team needs clear promotion rules:

  • Staging runs the latest pinned candidate build, not every new commit.
  • QA requests a new candidate when ready, not automatically.
  • Only fixes for the Friday release can change the candidate.
  • Everything else waits behind flags or stays out of the candidate.

Common mistakes that create churn and unstable QA

Most teams don’t fail because they picked the "wrong" model. They fail because day-to-day habits don’t match the model, so QA gets noisy and releases feel random.

A common problem is letting branches sit for days because "it isn’t ready." The code drifts from main, conflicts pile up, and QA ends up testing a mix of old and new work that nobody can reproduce.

Another is using GitFlow without a real freeze. A release branch is supposed to stabilize, but teams keep sneaking in "just one more" change. That turns the release branch into a second main line, and nobody knows what QA is signing off.

QA also becomes unstable when it’s treated like a dump environment for half-finished builds. If every commit goes to QA with no rules, testers spend time chasing moving targets instead of validating a release.

The mistakes that create the most churn:

  • Long-lived feature branches that merge late and break unrelated work.
  • Release branches that still accept new features.
  • No clear promotion path, so the build QA tested isn’t the build that ships.
  • Hotfixes done in a rush, then never merged back everywhere.
  • Environments with no owner, no purpose, and no reset plan.

Keep a rule set everyone can repeat:

  • QA tests only a pinned candidate.
  • You promote the same artifact from QA to production.
  • Each environment has an owner and a reset cadence.
  • Hotfixes flow back to the main line the same day.

Quick checklist for weekly shipping without surprises

Deploy with clear environments
Deploy to AppMaster Cloud or your preferred cloud, and keep QA and staging roles clear.
Create Project

Weekly shipping works when your team can answer a few boring questions with confidence. If you answer "no" to two or more, expect late fixes and QA whiplash.

  • Is there one branch you can safely deploy today? It should build, pass smoke tests, and avoid half-wired changes.
  • Do pull requests stay small and land within a day or two? Long-lived PRs usually mean stale feedback and bigger conflicts.
  • Does QA test a fixed build, not a moving target? QA should validate a specific build number or release candidate.
  • Can you keep unfinished work out of the release without drama? Feature flags, config toggles, or a clear scope-cut rule.
  • Can someone run a hotfix and rollback without guessing? A short runbook beats tribal knowledge.

If you want one measurable goal: pin QA to a release candidate and keep that candidate unchanged except for intentional fixes.

Next steps: pick one change to try next week

If your team is stuck debating trunk-based vs GitFlow, don’t redesign everything at once. Pick the one problem that costs the most time and run a small experiment for the next release.

If merge conflicts are the biggest pain, shorten branch lifetimes immediately. Aim to land work daily (or every other day), using feature flags when needed.

If QA instability is the biggest pain, start by pinning what QA tests and defining a simple promotion step.

A lightweight pilot:

  • Choose one repo and one team.
  • Set a branch age limit (for example, no branch older than 2 days).
  • Pin QA to one build and only change it through explicit promotion.
  • Track three numbers: merge-resolution time, QA rework hours, and hotfix time-to-production.
  • Review after 2-4 weeks and adjust.

If you want to reduce release pressure for internal tools or customer portals, a no-code platform like AppMaster (appmaster.io) can also help by generating production-ready backend, web, and native mobile apps from visual design. It still benefits from the same habits above: small changes, pinned QA candidates, and a clear promotion path.

FAQ

Which is better for weekly releases: trunk-based development or GitFlow?

Trunk-based development tends to fit weekly shipping best because it pushes you toward small, frequent merges and keeps main in a releasable state. GitFlow can work too, but it often adds bigger merge moments right when you want to be testing and stabilizing.

What’s the simplest way to explain the difference between trunk-based development and GitFlow?

Trunk-based means most work merges back to main quickly using short-lived branches, and unfinished behavior is kept safe with feature flags. GitFlow uses longer-lived branches like develop plus a release/* branch to stabilize, so integration is spread across more merge steps.

Why does trunk-based development usually reduce merge conflicts?

Frequent integration is the main reason: smaller pull requests, smaller diffs, and conflicts show up earlier while the context is fresh. The tradeoff is you need discipline around keeping main green with reliable CI and incremental changes.

Why do GitFlow teams often get big, stressful merges near release time?

Release branches and longer-lived feature work can drift, so conflicts pile up and then hit during feature-to-develop, develop-to-release/*, and release/*-to-main merges. That timing is painful for weekly shipping because those merges often happen during the stabilization window.

What practical habits cut merge pain no matter which model we use?

Keep pull requests small, merge at least daily, and pull in upstream changes regularly so you don’t drift. If a file is constantly contested, coordinate ownership or pair on the changes instead of working in parallel and colliding later.

How do we keep QA stable while developers keep merging code?

Pin QA to a specific candidate build and don’t change it mid-test unless you intentionally start a new test cycle. This stops QA from chasing a moving target and makes bug reports reproducible because everyone knows the exact build being tested.

How do we ship weekly if some features aren’t finished by release day?

Use feature flags (or similar toggles) so code can merge without turning on unfinished behavior for users. The default is to ship the code safely “off,” then enable it when it’s complete and verified, which keeps the weekly release train moving.

What’s the safest hotfix process we can follow under pressure?

Branch from the exact production commit, make the smallest possible fix, and get it deployed fast with the same checks you trust. Then immediately merge that fix back to every long-lived branch that will ship again, so the bug doesn’t reappear next week.

What are the most common hotfix mistakes in trunk-based vs GitFlow?

In trunk-based, the common failure is letting half-done work make main effectively not releasable, which makes hotfix validation risky unless flags are truly off by default. In GitFlow, the common failure is forgetting to merge a hotfix back into develop (and sometimes release/*), so the fix gets lost.

If part of our team uses AppMaster, do these branching and QA rules still apply?

Yes, as long as you treat AppMaster outputs like any other build artifact: pin what QA tests, promote the same candidate toward production, and avoid deploying random in-progress changes. The key is having clear rules for what gets regenerated and deployed, and when.

Easy to start
Create something amazing

Experiment with AppMaster with free plan.
When you will be ready you can choose the proper subscription.

Get Started