Odoo.sh

Odoo.sh Setup and Deployment: Git Workflows, Branches, and Modules That Actually Ship

By Shravya Shetty•••8 min read•
Loading...
Odoo.sh, the Odoo cloud platform: code moves from Development to Staging to Deployment

Getting Odoo live isn't just installing software — on Odoo.sh, it's a Git repository with opinions. Odoo.sh maps your branches directly to environments and rebuilds the instance from source on every push, which is powerful once you understand it and a source of confusing, silent failures if you don't. Most teams hit the same handful of problems the first time they deploy custom code through it, almost always for the same underlying reason: treating it like a plain code push instead of a full environment rebuild.

This article walks through what Odoo.sh setup actually involves, why deploying custom modules through Git trips people up, and the branch and module discipline that keeps deployments boring — which, for a production system, is exactly what you want.

Odoo.sh Deployment at a Glance

  1. Your Git repository is the deployment. Every push rebuilds that branch’s environment from source; there is no separate upload step.
  2. Branches map to stages. Feature branches get Development builds, Staging rehearses on a copy of production data, and one branch is Production.
  3. Declare every dependency. Python packages go in requirements.txt at the repository root, and manifests list what each module really needs.
  4. Staging before Production, always. It is the only place migration problems reliably show up before real users see them.
  5. Read the build log on every push. It shows the exact failing step and the warnings a “passed” build can still carry.

What Odoo.sh Actually Does

Odoo.sh is Odoo's own hosting and deployment platform, and it's built around a single idea: your Git repository is the source of truth for what runs in each environment. There's no separate deploy step where you upload a build artifact — you push to a branch, and Odoo.sh rebuilds and redeploys that environment directly from what's in the repository.

Odoo.sh → Branches to Environments
Development
feature/po-approval-flow
Disposable build per branch — spin up, test, tear down.
Staging
staging
Mirrors production data. Where merged features get rehearsed together.
Production
production
The live database. Every deploy here is a real migration.

Any branch gets a disposable Development environment for testing in isolation. A designated Staging branch mirrors production data, so changes can be rehearsed against something close to the real thing. And exactly one branch — Production — is the live database. Understanding that mapping is the entire foundation of working with Odoo.sh; almost every deployment problem traces back to a branch being used for something other than its intended stage.

Initial Configuration: More Than Connecting a Repository

Setting up a new Odoo.sh project involves more than pointing it at a Git repository. Custom modules need to live in a recognized addons path that Odoo.sh will scan on build. Any external Python packages a custom module depends on need to be declared in a requirements.txt at the repository root — Odoo.sh installs from that file on every build, it doesn't inherit whatever happens to be installed in a developer's local environment.

That last point causes more first-deployment failures than anything else on this list. A module runs perfectly on a developer's machine, because their local Python environment already has the package installed globally. It fails the moment it hits Odoo.sh, because the build environment only has what requirements.txt tells it to install.

The Real Challenge: Deploying Custom Code Through Git

On a recent Odoo.sh implementation, the pattern that caused the most rework wasn't one dramatic failure — it was a handful of small, repeatable mistakes that each looked minor in isolation but compounded quickly:

Deployment → Common Build Failures
CauseSymptom
External Python package not in requirements.txtModule works locally, build fails on Odoo.sh
Manifest missing a true module dependencyInstall order works by luck locally, fails on a clean build
Direct push to the production branchUntested change becomes a live migration with no rehearsal
Field type changed without a migration scriptUpdate runs, but existing data doesn’t convert correctly

Each of these produces the same experience: the build fails or the update runs cleanly but the module doesn't behave correctly, and the cause isn't obvious from inside Odoo itself — it's in the build log, which many teams don't check until something is already broken in front of a user.

Odoo.sh → Deployment Pipeline
git push
Odoo.sh build
Install / update modules
Automated tests
Live

A failure at any step stops the deploy there — the build log shows exactly which one, and the previous working version stays live until it's fixed.

The build log is the actual source of truth for a failed deployment. It shows exactly which step failed — dependency installation, module install, or a data migration — and the specific error, rather than the generic "something went wrong" a user sees in the app itself.

Managing Branches and Modules the Way Odoo.sh Expects

There's more than one way to structure a Git workflow for Odoo.sh, but they aren't equally good ideas. Pushing feature work directly to the production branch is the fastest way to deploy — and the fastest way to turn an untested change into a live, unrehearsed migration. It's the option we'd actively recommend against, even for small fixes.

The approach that actually holds up mirrors Odoo.sh's own environment model instead of fighting it:

  • Build on a feature branch first. Every change gets its own disposable Development build, so a broken module never touches a shared environment.
  • Merge to Staging before Production, always. Staging mirrors production data, which is the only place that reliably surfaces migration issues before they hit real users.
  • Declare every dependency explicitly. Manifest dependencies and requirements.txt entries should reflect what a module actually needs, not what happens to already be present in whatever environment it was last tested in.
  • Write a migration script for structural field changes. Renaming, retyping, or removing a field on a model with existing data needs an explicit migration step — Odoo won't infer the right conversion on its own.
  • Read the build log after every push, not just the pass/fail status. A build that "succeeds" can still install with warnings worth catching before Staging becomes Production.

Of the approaches available, Staging-before-Production isn't a close call. Odoo.sh already gives you a data-realistic rehearsal environment for free — the only failure mode is not using it, and pushing straight to Production because a change "feels small."

A Deployment Checklist Before You Trust a Push

For any Odoo.sh project, this is the order that avoids a broken production deploy:

  • Confirm every custom module's manifest lists its true dependencies — not just what happens to already be installed.
  • Add every external Python package to requirements.txt at the repository root.
  • Test on a Development branch before merging anywhere else.
  • Rehearse the merge on Staging against production-like data before touching the Production branch.
  • Write and test a migration script for any structural field or model change before it reaches Staging.
  • Read the build log on every push — not just whether the build passed, but what it warned about.

Odoo.sh Deployment: FAQ

How do Odoo.sh branches map to environments?

Odoo.sh has three branch stages: Production, Staging and Development. There can be only one production branch, and it runs the live database. Staging branches build on a neutralized copy of the production database, while development branches build a fresh database with demo data and run the unit tests by default.

Why does my custom module work locally but fail to build on Odoo.sh?

Usually an external Python package is installed on the developer’s machine but not listed in requirements.txt at the root of the repository. Odoo.sh installs Python dependencies from that file, not from anyone’s local setup. A module manifest that leaves out a real dependency causes the same kind of failure on a clean build.

Can I push changes straight to the Odoo.sh production branch?

Odoo.sh allows it, but Odoo’s own documentation warns that skipping Staging means changes are not checked against production data, so problems are more likely. We recommend building on a feature branch, merging to Staging, and only then merging to Production, even for small fixes.

Do I need a migration script when I change a field in a custom Odoo module?

Yes, if you rename, retype or remove a field on a model that already holds data, because Odoo will not work out the right conversion on its own. Odoo runs upgrade scripts from the module’s migrations folder only when the module is updated, so raise the module’s version number in its manifest and test the script on Staging first.

What happens if an Odoo.sh production deployment fails?

If a new build fails to load or update the production database, Odoo.sh keeps running the previous successful build, so the live system stays on the last working revision. The build log shows which step failed and the exact error. A build with warnings but no errors still goes live, so read the log even when a build passes.

Do configuration changes made in Staging carry over to Production?

No. Merging a staging branch into production merges only the source code, not changes made inside the staging database. Write configuration changes into the module’s XML data files and raise its version number, or repeat them by hand in production.

Why Odoo.sh Rewards Deployment Discipline

None of the failure modes here are exotic — a missing dependency, an untested merge, a field change with no migration path. What makes Odoo.sh unforgiving of them is that it rebuilds the entire environment from your repository on every push, so a small gap in discipline shows up immediately, in production, instead of staying invisible the way it might on a server you patch by hand.

Respect the branch-to-environment mapping Odoo.sh already gives you, declare dependencies explicitly, and rehearse every change on Staging first — and deployment becomes routine. Skip that discipline, and you'll be debugging a build log in front of a broken production instance instead of before one.

Deploying custom code to Odoo.sh and want it to actually stick?

Our Odoo implementation team can set up your branch strategy, module dependencies, and migration scripts correctly from the start — so your builds fail on a feature branch, not in front of your users.

Talk to Our Odoo Team
Odoo.shDeploymentGit WorkflowCustom ModulesOdoo ERP