Skip to content
shellhacks.dev
Git

How to Change a Git Remote URL From HTTPS to SSH Easily

Change a Git remote URL from HTTPS to SSH with git remote set-url: find the SSH address, test the connection, and fix credential and key problems.

6 min read
Summarize in AI
Illustration for "How to Change a Git Remote URL From HTTPS to SSH Easily": a shell script in an editor, a padlock and key, a loop arrow.

HTTPS remotes ask for a token again and again unless a credential helper is configured. SSH remotes use a key once loaded into an agent, and they work the same on every host. Switching an existing clone takes one command plus a test, and failures nearly always come from the key rather than from Git. The setup of keys is covered in generating SSH keys, and the commands assume Git 2.47 and OpenSSH 9.

See the current URL

Shell
git remote -v
Text
origin	https://github.com/example/app.git (fetch)
origin	https://github.com/example/app.git (push)

The HTTPS form has a scheme and slashes. The SSH form drops the scheme and uses a colon between the host and the path: [email protected]:example/app.git. A long form, ssh://[email protected]/example/app.git, also works and is needed when the server uses a non-standard port, as in ssh://[email protected]:2222/app.git.

Change it

Shell
git remote set-url origin [email protected]:example/app.git
git remote -v
Text
origin	[email protected]:example/app.git (fetch)
origin	[email protected]:example/app.git (push)

The remote name stays origin, and branches and history are untouched. To use a different URL only for pushing, add git remote set-url --push origin .... With several clones, repeat in each.

Test before pushing

Shell
ssh -T [email protected]
ssh -vT [email protected] 2>&1 | grep -i 'offering\|accepted\|denied'
Text
Hi example! You've successfully authenticated, but GitHub does not provide shell access.

That greeting is success. If you see Permission denied (publickey), the server did not accept any key offered. The verbose output lists which keys were tried. Common causes are a key that was never added to the account, a key not loaded in the agent (ssh-add -l shows loaded keys), or a different key offered first. The causes are listed in permission denied publickey.

Choose a key per host

Text
Host github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_github
  IdentitiesOnly yes

Put this in ~/.ssh/config. IdentitiesOnly stops the agent from offering every key and hitting the server's attempt limit, a cause of the "too many authentication failures" error. Details are in the SSH config guide. For two accounts on one host, define two host aliases such as github-work with different keys and use that alias in the URL.

Why the URL type matters more than it looks

An HTTPS remote authenticates every push with a username and a token, and the token has to live somewhere: a credential helper, the OS keychain or, worse, the URL itself. A token embedded in the remote URL shows up in git remote -v, in shell history and in the .git/config file, which gets copied into backups and sometimes into container images. An SSH remote keeps the secret in a private key file that never leaves the machine, and the remote URL contains nothing sensitive. That difference is the main practical reason to switch, ahead of convenience.

SSH has its own costs. A key that is not in an agent prompts for its passphrase on every operation, and a new machine needs the public key uploaded to the hosting account before anything works. For a laptop that you use daily, an agent holding a decrypted key for the session removes the friction. For a shared build server, a read-only deploy key attached to one repository is safer than a personal key, because losing it exposes one project rather than an account.

Different shapes of the same URL

The short form [email protected]:owner/repo.git is what most hosts show on their clone button, and it is the scp-like syntax: a user, a colon and a path relative to the user's home. It cannot carry a port. The long form ssh://git@host:2222/owner/repo.git uses a real URL, so the port goes after the host and the path after a slash. Mixing them is a common error: writing git@host:2222/owner/repo.git makes Git treat 2222/owner/repo.git as a relative path and the connection goes to port 22.

Self-hosted servers add one more variation. Some run the Git SSH service under a dedicated user that is not git, and some put repositories under a path prefix. Copy the exact URL the server displays rather than rewriting the HTTPS one by hand, and keep the .git suffix when the host shows it, since a few servers treat the two forms as different repositories.

Rewriting URLs without editing every clone

When a team moves from HTTPS to SSH, changing each clone by hand does not scale. Git can rewrite URLs on the fly with url.<base>.insteadOf. Setting git config --global url."[email protected]:".insteadOf "https://github.com/" makes every HTTPS GitHub URL, including those inside submodule definitions and scripts, go out over SSH without touching any repository. The remote stored in .git/config still shows HTTPS, which can confuse a reader, so check the effective address with git remote get-url --push origin or by running a command with GIT_TRACE=1, which prints the real connection.

The reverse rewrite is useful in CI. A job that checks out over SSH on a developer machine can use a token over HTTPS in a pipeline, with the same repository configuration, by setting the rewrite only in the pipeline's global configuration. The repository files stay identical, and the credential choice becomes an environment decision rather than something committed to the project.

What breaks after the switch

Three things surprise people. First, a stored HTTPS credential does not stop working; Git stops using it, and the old token still sits in the keychain until someone removes it. Second, tools that parse the remote URL, such as release scripts or badge generators, may expect the HTTPS form and fail on the scp-like one, so test them. Third, the first connection to a host asks whether to trust its host key. Verify the fingerprint against the host's published list instead of answering yes by habit, because that prompt is the only protection against connecting to an impostor.

Where this does not apply

Networks that block port 22 can break SSH while HTTPS works; GitHub offers SSH over port 443 at ssh.github.com. In CI you often prefer HTTPS with a short-lived token over a stored key. Submodules keep their own URLs in .gitmodules, so changing the parent does not change them; see git submodules. See the GitHub SSH documentation and the git-remote manual.

One more check after the switch: run git fetch and git push --dry-run. The first confirms read access and the second confirms write access without sending anything. If you use a credential helper for HTTPS elsewhere, the cached token stays in the helper and does no harm, though you can remove it with git credential reject or in the keychain. A fine-grained deploy key is the better choice in automation, and deploy keys explain how to scope it to one repository.

Taggedgitssh
Share

Keep reading

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.