Deploy With Git Push Without GitHub — No OAuth Connection Needed

·7 min read·Updated
gitdeploymentdockerci-cdhow-to

You can deploy with git push without GitHub, without GitLab, and without granting any platform OAuth access to your account. JustRunMy.App gives each app its own HTTPS git remote with its own generated credentials; you add it as a remote, push your branch to deploy, and the platform builds your Dockerfile and starts the container while the build output streams back into your terminal. Your code doesn't need to live on a third-party host at all — a plain local git repository is enough. There's nothing to authorize, no repo-access scope to grant, and nothing to revoke later.

Why most platforms want your GitHub account first

The modern PaaS onboarding flow is: sign up, connect GitHub, pick a repo. That connection is an OAuth grant, and it's a real decision — you're giving a third party standing read access to source code, not just the one project you wanted to deploy.

It's also load-bearing rather than optional. On Render, auto-deploys require a connected GitHub, GitLab, or Bitbucket account; services built from a prebuilt Docker image or a public repository URL have to be deployed manually instead (Render docs). "Deploy without GitHub/GitLab" is an open item on their public feature-request board, largely from people who used to git push heroku from a local checkout (Render feedback).

Heroku does still offer the push-to-deploy remote, with a caveat in its own docs: it is "not intended to be a stable git repository," and they recommend keeping your codebase on GitHub, GitLab, or Bitbucket (Heroku Dev Center).

That caveat is the right mental model, and it's worth keeping: a deploy remote is a delivery mechanism, not a code host. Where your history actually lives is a separate decision — and it should stay separate.

How the deploy remote works

Pick Git Push on the Advanced tab of Create new application.

The Advanced tab of Create new application in the JustRunMy.App panel, with Git Push listed as the recommended deploy option alongside Docker Push, Prefab Template, and Existing Image

The page gives you one command — a git push to an HTTPS URL, targeting the deploy branch:

The Use Git for deployment page in the JustRunMy.App panel, showing a single git push command with the deploy URL masked, and a Wait for Deploy step

The URL is hidden behind a mask until you hover it, because it carries a password. Copy it with the Copy button and it looks like this:

git push -u https://<user>:<password>@justrunmy.app/git/<repo-id> HEAD:deploy

A few things are worth unpacking there:

  • It's plain HTTPS git, not SSH. No key to generate, upload, or rotate. It speaks the standard smart-HTTP protocol, so any git client works — including one inside a CI runner.
  • The credentials are generated per repository. Each deploy remote gets its own random username and password, unrelated to your account login. Scope is one app's deploy endpoint and nothing else.
  • HEAD:deploy pushes your current branch to the remote's deploy branch. Your local branch can be called anything; the refspec is what matters.
  • No remote repo needs to exist first. A local git init and a commit is the whole prerequisite.

Because the URL contains a live password, treat it as a secret — which is why the panel masks it on screen until you hover. Keep it out of commits and out of shared terminal recordings too. If you'd rather not have it in your shell history, add it as a named remote once (git remote add deploy <url>) and push to the name afterward.

Two branches: deploy and build

The remote tracks exactly two branch names, and they do different things:

Push to What happens
deploy Build the image, then start or restart the app with it
build Build the image and attach it to the app — but don't restart
anything else Nothing. You get a message saying the branch isn't tracked

build is the useful one for anyone who dislikes surprise restarts: bake the image on push, then restart deliberately when you're ready. That "nothing happened" message on other branch names is intentional too — pushing a feature branch to the deploy remote won't take your app down.

Your repo needs a Dockerfile at the root

The build is a Docker build, so the pushed commit must contain a Dockerfile at the repository root. The platform checks for it before starting the build and tells you plainly if it's missing, rather than failing halfway through with a Docker API error.

If you don't have a Dockerfile and don't want to write one, use the zip-upload path instead — the Runny AI Agent analyzes the project and generates the build configuration for you. The two paths are complementary: the agent is for getting from "a folder of code" to "a running app," and the git remote is for shipping repeatedly once you know what the container should be.

What you see while it builds

The push doesn't return immediately. The Docker build runs server-side and its output streams back over the same git connection, so docker build steps appear in your terminal as they happen, prefixed and interleaved with the push progress. When it finishes you get a confirmation that the image was built and the app was created or restarted.

That matters more than it sounds. A failed build is visible right there in the push output — you don't have to switch to a dashboard, find the deploy, and open a log viewer to learn that step 7 failed.

First push versus later pushes

The first push creates the app. You don't create it in the dashboard first — the platform builds the image, creates the application, attaches the image, and starts it, then redirects the create-application page to your new app once it appears. New apps start with a small default CPU and memory allocation, which you can raise afterward from the app's settings within your quota.

Every push after that updates the same app. Once an app is bound to the remote, pushing to deploy rebuilds the image and restarts that app in place. The app also gets its own Deploy from Git panel showing its push command, so you can come back for it later.

Honest limits

Worth knowing before you wire it into anything:

  • The remote is push-only. It advertises git-receive-pack and refuses anything else, so you can't git clone or git fetch from it. This is a deploy endpoint, not a backup of your code — keep your real repository wherever you already keep it.
  • One push at a time per repository. Concurrent pushes to the same remote are rejected with a conflict rather than racing each other. In CI, serialize deploys to a given app.
  • Only deploy and build are tracked. There's no per-branch environment mapping.
  • The push URL is a credential. Anyone holding it can deploy to that app.
  • Dockerfile required, as above.

FAQ

Can I deploy without a GitHub account?

Yes. You push a local git repository directly to a per-app HTTPS deploy remote. No GitHub, GitLab, or Bitbucket account is involved, and no OAuth authorization is requested.

Do I need to grant OAuth access to my source code?

No. Nothing reads your git host. You push the commit you choose, and only that commit is transferred.

Do I need SSH keys?

No. The remote is HTTPS with Basic authentication, using a username and password generated for that repository. Any standard git client can push to it.

Which branch triggers a deploy?

deploy builds and restarts the app; build builds the image without restarting. Pushing any other branch name does nothing and tells you so.

Can I clone from the deploy remote?

No — it accepts pushes only. Treat it as a delivery endpoint and keep your canonical repository wherever you normally host it.

Can I use this from CI?

Yes. It's ordinary HTTPS git, so a pipeline can push to it with the URL held as a secret. Just don't run two deploys against the same app at once — the second is rejected as a conflict.

What if my project has no Dockerfile?

Add one at the repository root, or use the zip-upload flow, where the AI agent works out the build configuration from your source instead.

Wrapping up

Connecting a git host is convenient when your code is already there and you want push-to-deploy on every merge. It's friction when it isn't — a private project, a client's codebase you'd rather not grant a third party standing access to, or a repo that simply lives on a server you own. A per-app deploy remote covers that case without asking you to reorganize where your code lives: git remote add, git push, watch the build, done. And because it's push-only with its own scoped credentials, revoking access to it doesn't touch anything else you own.