01 · THE CHOICE

Three ways to authenticate, and when each is right.

MethodHow it worksBest forWatch out for
SSH keysA key pair per machine; the public half lives on your accountYour own machines, long-lived setups, serversBlocked outbound on some corporate networks, though port 443 works around it
HTTPS with a tokenA personal access token stored in a credential helperRestricted networks, CI, short-lived accessTokens expire, and scopes are easy to over-grant
GitHub CLIBrowser sign-in that configures Git for youGetting productive in two minutesYou still want a key for servers and automation

The pragmatic answer for a personal machine is SSH. There is nothing to expire, nothing to paste, and revoking access to one machine is a single click that does not affect anything else.

02 · THE KEY

One ed25519 key, per machine, with a passphrase.

SHELL · GENERATE AND REGISTER
# The comment identifies the machine, not you. It appears in GitHub.
ssh-keygen -t ed25519 -C "desktop-windows-2026"

# Start the agent and load the key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# Copy the PUBLIC half into GitHub, Settings, SSH and GPG keys
cat ~/.ssh/id_ed25519.pub

# Confirm it works
ssh -T git@github.com

On Windows, PowerShell has OpenSSH built in. Start the agent as a service once and it will hold your key across sessions:

POWERSHELL (ADMIN) · PERSISTENT AGENT
Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

Four rules worth following

  • ed25519, not RSA. Shorter, faster and the current default. Use RSA only for a system that genuinely cannot accept anything else.
  • Set a passphrase. The agent means you type it once per session. A key without one is a plaintext credential in a predictable location.
  • One key per machine. Copying a key between computers means you can never revoke one without breaking the others.
  • Never commit a private key. Automated scanners find them within minutes of a push, including in a repository you later make private.

If SSH is blocked on your network, GitHub accepts SSH over port 443. Add a host entry for ssh.github.com on port 443 in your SSH config and it behaves identically.

03 · MULTIPLE ACCOUNTS

Work and personal on one machine, without confusion.

The reliable approach is one key per account plus SSH host aliases, so the remote URL itself selects the identity.

~/.SSH/CONFIG
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_personal
  IdentitiesOnly yes

Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes
SHELL · USING THE ALIAS
# Clone through the alias to use the work identity
git clone git@github-work:company/project.git

# Fix an existing repository
git remote set-url origin git@github-work:company/project.git
git remote -v

IdentitiesOnly yes matters more than it looks: without it, the agent offers every loaded key in turn, and the server accepts the first one that works — which may not be the account you intended.

Getting the commit author right too

~/.GITCONFIG · CONDITIONAL IDENTITY
[user]
  name = Your Name
  email = personal@example.com

[includeIf "gitdir:~/work/"]
  path = ~/.gitconfig-work

Every repository under ~/work/ then picks up the work name and email automatically. This prevents the other half of the problem: correct authentication with the wrong author on the commit.

04 · SIGNING

Sign with the SSH key you already have.

Commit signing proves a commit came from you rather than from anyone who can set a name and email — which is anyone. Modern Git can sign with an SSH key, so there is no reason to set up GPG unless you already use it.

SHELL · SSH COMMIT SIGNING
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
git config --global tag.gpgsign true

# Verify locally
git log --show-signature -1

Then add the same public key a second time in your GitHub settings, with the type set to Signing Key rather than Authentication Key. One key, two registrations, two purposes. Commits then show the verified badge.

  • Enable vigilant mode in your GitHub settings once every machine signs. Unsigned commits attributed to you are then flagged as unverified rather than silently trusted.
  • Register every machine’s key as a signing key, or commits from the others will show as unverified.
  • Web edits sign automatically with GitHub’s own key, which is expected and fine.

Signing is not a formality on a public repository. Anyone can author a commit under your name and email. The signature is the only thing that distinguishes your work from an impersonation of it.

05 · TOKENS

When you do need a token, scope it narrowly.

Automation and restricted networks still need HTTPS with a token. The failure mode there is not leakage so much as over-permission.

  • Prefer fine-grained tokens. They target specific repositories with specific permissions, instead of granting a scope across everything you can see.
  • Set an expiry. A token that never expires is a permanent credential you will forget about. Ninety days is a reasonable default.
  • One token per purpose. Separate tokens for CI, a local script and a deployment mean you can revoke one without an outage everywhere else.
  • Never put a token in a URL. It ends up in shell history, in logs, and in the repository configuration file.
  • Use the credential manager. Git Credential Manager on Windows stores tokens in the OS credential store rather than in a plaintext file.
  • In CI, use the provided identity. GitHub Actions supplies a scoped token for the workflow run; a long-lived personal token is a downgrade in both security and convenience.

06 · ROTATION

The five minutes after a credential is exposed.

Committed a private key, pushed a token, or lost a laptop. In that order, immediately:

STEP—01 Revoke first

Delete the key or token in GitHub settings before anything else. Cleaning history while the credential is still valid is the wrong order.

STEP—02 Generate a replacement

New key pair, new passphrase, registered for both authentication and signing.

STEP—03 Audit the account

Review security log, active sessions, authorised applications and deploy keys. Look for anything you did not create.

STEP—04 Then clean the history

Rewrite it out of the repository, force-push, and ask GitHub support to expire cached views of the old objects.

Treat any exposed secret as compromised, permanently. Public repositories are scanned continuously by automated systems; a key pushed and deleted a minute later has been collected. Rotate it rather than hoping.

Routine hygiene

  • Review your registered SSH keys twice a year and remove machines you no longer own.
  • Give each key a comment that identifies the machine, so the list is meaningful later.
  • Enable secret scanning and push protection on repositories that accept contributions.
  • Keep two-factor recovery codes somewhere that does not depend on the account they protect.

07 · QUICK ANSWERS

GitHub authentication, briefly.

Should I use SSH or HTTPS for GitHub?

SSH for your own machines: nothing expires, nothing gets pasted, and revoking one machine does not affect the others. HTTPS with a token is better on restricted networks where outbound SSH is blocked, and in automation. If SSH is blocked, GitHub also accepts SSH over port 443.

What type of SSH key should I create?

ed25519. It is shorter, faster and the current default, and GitHub has supported it for years. Use RSA with at least 4096 bits only when you need to talk to a system that genuinely cannot accept ed25519. Always set a passphrase and let the SSH agent hold it for the session.

How do I use two GitHub accounts on one machine?

Create a separate key per account, define a host alias for each in your SSH config with IdentitiesOnly set to yes, and clone through the alias. Add a conditional include in your global Git config so repositories under a work directory automatically use the work name and email on commits.

How do I get the verified badge on my commits?

Configure Git to sign with SSH: set gpg.format to ssh, point user.signingkey at your public key, and enable commit.gpgsign. Then add the same public key to GitHub a second time with the type set to Signing Key. Register every machine key you use, or commits from the others will show as unverified.

I committed a private key. What now?

Revoke it in GitHub settings immediately, before cleaning anything. Generate a replacement, review your account security log, active sessions, authorised applications and deploy keys, and only then rewrite the repository history. Assume the exposed key was collected by automated scanners regardless of how quickly you deleted it.