TechEarl

Git SSH vs HTTPS Remotes: Which Should You Use?

SSH and HTTPS are two ways to connect Git to a remote like GitHub. Here is how each authenticates, when to pick which, and how to switch with git remote set-url.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
Comparison of Git SSH and HTTPS remote URLs and how each authenticates to GitHub

A Git remote can use one of two URL schemes to talk to a host like GitHub: SSH or HTTPS. They do the same job (push and pull), but they authenticate differently. HTTPS uses your account plus a token (or a credential helper); SSH uses a key pair you generate once and register with the host. For most personal development either works. If you push many times a day and do not want to deal with tokens, set up an SSH key once and use SSH.

You can tell which scheme a remote uses by looking at its URL:

bash
git remote -v
text
origin  git@github.com:you/repo.git (fetch)        # SSH
origin  https://github.com/you/repo.git (fetch)     # HTTPS

An SSH URL starts with git@host: and a colon before the path. An HTTPS URL starts with https:// and uses a slash. That is the fastest way to know what a clone is using.

How HTTPS authenticates

When you push over HTTPS, the host needs to confirm you are allowed to write to the repo. GitHub stopped accepting your account password for this in August 2021. You now authenticate with a personal access token (PAT) used in place of the password, and Git typically remembers it through a credential helper so you are not pasting it every time.

The first push prompts for credentials:

bash
git push origin main
text
Username for 'https://github.com': you
Password for 'https://you@github.com': <paste your personal access token here>

To stop the prompts, enable a credential helper that stores the token. On macOS, Git ships with the Keychain helper:

bash
git config --global credential.helper osxkeychain

On Linux, the libsecret helper or the cache helper both work:

bash
git config --global credential.helper libsecret

If you ever paste your old password by reflex you will hit the error that Support for password authentication was removed covers. The fix there is the same idea: generate a token and use it as the password.

How SSH authenticates

SSH does not use your account password or a token at all. You generate a key pair once, keep the private key on your machine, and upload the public key to the host. After that, every push and pull authenticates silently with the key.

Generate a key with the modern Ed25519 type:

bash
ssh-keygen -t ed25519 -C "you@example.com"

Then add the public key (the .pub file) to your GitHub account. If you need the full cross-platform key-generation walkthrough first, here is how to create an SSH key on any OS; to register it, adding an SSH key to GitHub covers starting the agent and testing the connection. Once the key is registered you can confirm it works:

bash
ssh -T git@github.com
text
Hi you! You've successfully authenticated, but GitHub does not provide shell access.

That message is the success case. If you instead see Permission denied (publickey), the host could not match your key. The page on fixing Permission denied (publickey) walks through the usual causes: the agent is not running, the key was never uploaded, or the wrong key is being offered.

SSH vs HTTPS at a glance

AspectSSHHTTPS
URL formatgit@github.com:you/repo.githttps://github.com/you/repo.git
CredentialKey pair (private key + uploaded public key)Personal access token (used as the password)
Set up onceGenerate key, upload .pubGenerate token, store via credential helper
Per-push frictionNone after the key is loadedNone after the helper stores the token
Works behind strict firewallsSometimes blocked (port 22)Usually fine (port 443)
Two-factor accountsKey is unaffected by 2FAToken required (password will not work)
Best forFrequent pushing from your own machineCI, locked-down networks, quick one-off clones

Neither is more secure than the other in any meaningful sense for normal use; both encrypt the connection. The real differences are friction and network constraints.

When to pick which

Reach for SSH when the machine is yours and you push often. The one-time key setup pays for itself the first day. It also sidesteps token expiry: an Ed25519 key does not expire, so you are not regenerating tokens every few months.

Reach for HTTPS when:

  • You are on a corporate or campus network that blocks outbound SSH (port 22). HTTPS over 443 almost always gets through. GitHub also offers SSH over the HTTPS port as a fallback if you must use keys on such a network.
  • You are setting up CI or a build server, where a scoped token is easier to rotate and revoke than managing keys.
  • You are doing a quick read-only clone of someone else's public repo and do not care about pushing. The same decision shows up the moment you clone: SSH vs HTTPS is a clone-time choice too, since the URL you copy determines the scheme.

If you are still getting your bearings with remotes generally, the Git for beginners guide covers what a remote is and how origin gets wired up in the first place. And if a clone of an existing project is where you are starting, see how to start working on an existing Git project.

Switching an existing remote between SSH and HTTPS

You do not have to re-clone to change schemes. Change the URL in place with git remote set-url.

To switch a remote from HTTPS to SSH:

bash
git remote set-url origin git@github.com:you/repo.git

To switch it back from SSH to HTTPS:

bash
git remote set-url origin https://github.com/you/repo.git

Confirm the change took:

bash
git remote -v

Nothing else moves. Your branches, history, and local config are untouched; only the address Git dials for origin changed. This is the cleanest fix when you cloned over HTTPS, got tired of the token prompts, and want to move to keys (or the reverse, when SSH is blocked on a new network).

If you have not added the remote at all yet, you use git remote add instead, which is part of adding Git to an existing project; and if Git complains that remote origin already exists, set-url is exactly the command that resolves it.

Deploy keys: SSH access scoped to one repo

A normal SSH key is tied to your account and can reach every repo you have access to. That is wrong for a server. If a production box only needs to pull one repository, you do not want a key on it that could touch everything you own.

A deploy key solves this. It is an SSH key pair registered against a single repository rather than your account. The server gets a key that can pull (and optionally push to) exactly that one repo and nothing else.

The setup is the same key generation, run on the server:

bash
ssh-keygen -t ed25519 -C "deploy@myserver" -f ~/.ssh/deploy_myrepo

Then add the public key in the repository's own settings (Settings, then Deploy keys on GitHub) instead of your account settings. Leave it read-only unless the server genuinely needs to push. Read-only is the right default for a deploy target that only pulls new code. The same access-control surface applies on the server side, where how a pre-receive hook can decline a push shows the host rejecting writes it does not want.

This pattern is the foundation of pull-based deployment. If you are building a deploy flow around it, deploying with a Git post-receive hook and push-to-deploy with GitHub Actions both build on a server that can authenticate to the repo without a human pasting credentials. On the security side, never commit a private key into the repo; the article on removing a secret from Git history exists because that mistake is common, and a leaked key is exactly the kind of thing the exposed .git directory attack feeds on.

A note on changing the URL after a security incident

If a token leaks, you revoke it in your account settings and the HTTPS remote simply stops working until you authenticate with a new one. If a private key leaks, you remove its public counterpart from the host (your account or the repo's deploy keys) and generate a fresh pair. In both cases the remote URL itself does not need to change; you are rotating the credential, not the address. Knowing which one a remote uses tells you exactly where to go to cut access.

Sources

Authoritative references this article was fact-checked against.

Tagsgit ssh vs httpsGitVersion ControlSSHGitHubAuthentication

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts