Skip to content
Menu
← All posts
Note3 min read

Enforce SSH instead of HTTPS for Git operations

GitHub stopped accepting passwords for Git this month. Keys were the better answer anyway — here is a setup that also survives tools with HTTPS URLs baked in.

  • Software
  • Engineering

Ten days ago GitHub stopped accepting account passwords for Git operations over HTTPS. If you push over HTTPS you now paste a personal access token instead — a longer secret, kept in the same place the password was, expiring on a schedule you have to remember.

SSH avoids the question. You generate a key pair once, keep the private half on your machine, hand the public half to the host, and stop typing credentials for Git entirely. It also authenticates the server to you, which a token does not.

Setup takes about five minutes. The last two steps are the ones most guides leave out, and they are the reason this sticks.

Generate a key

ssh-keygen -t ed25519 -C "personal github" -f ~/.ssh/personal-github

Ed25519 rather than RSA: shorter keys, faster handshakes, and no key-size argument to get wrong. If you have to talk to something older than OpenSSH 6.5, -t rsa -b 4096 is the fallback.

Name the key after what it unlocks — personal-github, work-gitlab — and make one per account rather than one per machine. Accounts get revoked individually, and a key named id_ed25519_2 tells you nothing on the day you need to revoke it.

Use a passphrase. The agent means you type it once per session, not once per push.

Add the public key to the host

Copy the public half — the file ending in .pub, never the other one:

pbcopy < ~/.ssh/personal-github.pub

Then paste it into your account settings: GitHub, GitLab, or Bitbucket.

Rewrite HTTPS URLs to SSH

A key does nothing while your remotes still say https://. Instead of fixing them one repository at a time, tell Git to substitute globally, in ~/.gitconfig:

[url "ssh://git@github.com/"]
  insteadOf = https://github.com/

[url "ssh://git@gitlab.com/"]
  insteadOf = https://gitlab.com/

[url "ssh://git@bitbucket.org/"]
  insteadOf = https://bitbucket.org/

Every HTTPS URL for those hosts is now rewritten before the request leaves your machine — including the URLs you did not write. That covers CocoaPods specs, go get, npm dependencies that point at a Git repository, submodules cloned from someone else’s .gitmodules, and CI scripts you would rather not touch.

This is the step that turns “I set up a key” into “I never see a credential prompt again”.

Tell SSH which key to use

Git speaks SSH now, but SSH still has to choose a key. Left alone it tries the default names, so a key called personal-github is never offered. In ~/.ssh/config:

Host github.com
  User git
  IdentityFile ~/.ssh/personal-github
  IdentitiesOnly yes
  AddKeysToAgent yes

Host gitlab.com
  User git
  IdentityFile ~/.ssh/work-gitlab
  IdentitiesOnly yes
  AddKeysToAgent yes

IdentitiesOnly yes earns its line. Without it SSH offers every key the agent holds, in whatever order it likes, and a host that sees the wrong key first can reject you before the right one is ever tried — which reads as a permissions bug and is not one.

On macOS, add UseKeychain yes to each host block and the passphrase survives a restart.

Check it

ssh -T git@github.com

A greeting with your username means the key works. To confirm the rewriting, clone something over HTTPS and watch it go through without a prompt:

git ls-remote https://github.com/omaralbeik/SwifterSwift.git

If that returns refs without asking for anything, both halves are in place: Git is rewriting the URL, and SSH is picking the right key for it.

Latest posts

Topics

See all results