All guides

Deploy from your Git repository

Connect a repository, deploy a branch, and understand what happens between a push and a running environment.

Verified on August 12, 2026

Deploying here is not restarting a server with new files on it. Every deploy builds an image from one specific commit and then runs that image. Knowing this explains most of what you will see: why a deploy takes minutes rather than seconds, why the version running can always be named, and why going back is instant.

What you need

  • An instance with at least one environment.
  • The git.manage permission to connect a repository, and environments.deploy to deploy one.
  • A repository containing Odoo modules. Private repositories additionally need the provider authorisation described below.

Connect the repository

Open your instance, go to the Git integration tab and choose Connect a repository. You can connect an existing repository or create a new one.

An instance's Git integration tab with no repository connected: the Connect Repository button and three collapsed sections covering module detection, Python dependencies and size limits.
The Git integration tab before anything is connected.

Connecting a public repository read-only works immediately. Anything else — a private repository, webhooks, auto-deploy, creating branches — needs Provider authorisation first, through Connect provider. If the OAuth client is not configured for your provider yet, the interface says so rather than failing halfway through.

The connect dialog: provider picker, "Connect an existing repository" and "Create a repository" tabs, a Provider Authorization panel, repository and initial branch fields, and a public read-only switch.
The authorisation panel is what separates a public repository from a private one.

The credential stored for the repository is encrypted at rest and used only to read the branch being built, plus to write when you explicitly ask for a commit.

What a deploy actually does

When you deploy a branch, four things happen in order:

  1. The commit at the head of that branch is resolved and pinned. From here on the deploy refers to that commit, not to the branch.
  2. A build produces an image containing your modules on top of the environment's base image.
  3. The image is pushed to the registry under a tag derived from the commit.
  4. The environment is switched to that image, and the Odoo database is migrated if needed.

The four steps of a deploy: commit pinned, image built, pushed to the registry, environment switched and migrated.
The branch is how you pick the commit; after that, the image is what counts.

The consequence worth remembering: what is running is always a named version. Not "the latest state of the branch" — a specific image, built from a specific commit, that can be redeployed exactly as it was.

Auto-deploy on push

Enable Auto-deploy on push and every push to the connected branch runs the same sequence.

A connected repository card: full name, branch, webhook status, the last commit with its Sync and Deploy buttons, and the "Auto-deploy on push" switch turned on.
The webhook status on the third line is what to check when a push does nothing.

This works through a webhook, and the webhook is verified with a secret specific to that repository, not a global one. If the secret does not match, the push is rejected silently at the gate — no build, no deploy, no error on your screen, because as far as the platform is concerned nothing was pushed.

That same gate drives module synchronisation. So if you push and nothing at all happens — neither a deploy nor an updated module list — check the webhook secret before you look at anything else. It is the single most likely cause and it produces no visible error.

Where the addons come from

Your repository tree is not flattened. Each directory that contains Odoo modules becomes its own entry in addons_path, so a repository laid out like this:

repo/
  addons/          -> one addons root
  enterprise_ext/  -> another addons root
  tools/           -> not a module directory, ignored

gives Odoo two addons roots rather than one merged folder. Modules with the same name in two roots stay distinct, and the order is preserved.

If your environment runs a plain base image without a build, Odoo has no /mnt/extra-addons to read and your modules will not appear. The environment page shows a Build & deploy action in that case — that is what turns the repository into an image.

When a build times out

Two different limits apply, and knowing which one you hit saves time:

LimitWhat it covers
BUILD_JOB_TIMEOUTThe build job itself — cloning, assembling, pushing the image
BUILD_TIMEOUT_SECONDSThe platform's patience for the whole build to report back

An environment's Builds tab: a build with a red TIMEOUT status, its commit, a 3600s duration and the message "Build exceeded BUILD_JOB_TIMEOUT", followed by a SUCCESS build that took 480s.
The duration next to the status is what separates a timed-out build from a failed one.

A build that runs long is not necessarily stuck. Installing modules into a fresh database is the slow part, and it grows with the number of modules — a single module is fast, a dozen is not. If a build times out reproducibly with many modules, the limit is the thing to raise, not the code to change.

Going back to a previous version

Deploy an earlier version puts a previous build back in service. It redeploys the exact image, as it was built — nothing is rebuilt, so it is fast and there is no chance of a different result.

The redeploy confirmation: "Deploy this version?", followed by "This puts main · a1c93f4 live on this environment, in place of what is running today", with Cancel and Deploy this version buttons.
The confirmation names the exact version that will replace the one in service.

One thing it does not do: it does not migrate databases backwards. The code returns to the earlier version; the database stays where the last migration left it. For a schema change that is usually fine for a short rollback and is not a way to undo a migration. If you need the data as it was, restore a backup instead — a different operation, and it comes in two forms: Restore overwrites this environment (a safety backup is taken first and the environment restarts), while Clone to a new environment leaves this one untouched. The Duplicate production to test guide covers both.