git clone with ssh key

Git Clone With an SSH Key: Setup, Command, Fixes

By Zest | Updated | 8 min read
A laptop on a desk with a terminal on screen and the words SSH Git Clone

To clone a Git repository with an SSH key, generate a key with ssh-keygen -t ed25519, add the public half (~/.ssh/id_ed25519.pub) to your GitHub, GitLab or Bitbucket account, and clone with the repository’s SSH URL:

git clone git@github.com:OWNER/REPO.git

The SSH URL is under the Code button on GitHub (SSH tab) and GitLab (Clone with SSH). It starts with git@, not https://. The rest of this guide covers each step on macOS, Linux and Windows, cloning with a specific key, and the errors you are likely to hit.

The git clone SSH command

The URL has the form git@HOST:OWNER/REPO.git:

# GitHub
git clone git@github.com:OWNER/REPO.git

# GitLab
git clone git@gitlab.com:GROUP/PROJECT.git

# Bitbucket
git clone git@bitbucket.org:WORKSPACE/REPO.git

# Clone into a folder with a different name
git clone git@github.com:OWNER/REPO.git my-folder

ssh://git@github.com/OWNER/REPO.git is the same address in URL form. If the clone fails with Permission denied (publickey), your key isn’t set up yet: work through the steps below, or jump to Troubleshooting.

1. Generate an SSH key

Check whether you already have one:

ls -al ~/.ssh

Files named id_ed25519 and id_ed25519.pub mean you do. Otherwise, create a key. Use your Git account’s email as the comment:

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

Press Enter to accept the default path (~/.ssh/id_ed25519), then set a passphrase. The passphrase encrypts the private key on disk, so a copied key file is useless without it. You will rarely type it, because the ssh-agent remembers it (step 2).

You now have two files:

  • ~/.ssh/id_ed25519: the private key. It never leaves your machine; don’t copy it anywhere.
  • ~/.ssh/id_ed25519.pub: the public key. This is what you give to GitHub, GitLab or Bitbucket.

Ed25519 is GitHub’s recommended key type. If a legacy system can’t use it, fall back to ssh-keygen -t rsa -b 4096 -C "you@example.com". With a hardware security key, use -t ed25519-sk.

On Windows, Windows 10 and 11 include the OpenSSH client, so the same ssh-keygen command works in PowerShell. Git Bash, which comes with Git for Windows, works too.

2. Add the key to the ssh-agent

The agent holds your unlocked key in memory, so you enter the passphrase once instead of on every git pull.

macOS: add this to ~/.ssh/config (create the file if it doesn’t exist):

Host github.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

Then store the passphrase in the macOS keychain:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Linux and Git Bash:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

Windows (PowerShell): start the agent service once, from an administrator window, then add the key from a normal one:

Get-Service -Name ssh-agent | Set-Service -StartupType Manual
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

These steps follow GitHub’s guide to generating a key.

3. Add the public key to your Git host

Copy the public key:

# macOS
pbcopy < ~/.ssh/id_ed25519.pub

# Linux (or just cat the file and copy the line)
xclip -selection clipboard < ~/.ssh/id_ed25519.pub

# Git Bash on Windows
clip < ~/.ssh/id_ed25519.pub

In PowerShell, use Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | Set-Clipboard.

  • GitHub: Settings › SSH and GPG keys › New SSH key. Choose Authentication Key, give it a title that names the machine (“Work laptop 2026”), and paste the key. With the GitHub CLI: gh ssh-key add ~/.ssh/id_ed25519.pub --title "Work laptop".
  • GitLab: your avatar › Edit profile › SSH Keys › Add new key. GitLab lets you set an expiry date.
  • Bitbucket: Personal settings › SSH keys › Add key.

Name every key after the machine it lives on. When a laptop is lost, you’ll know which key to delete.

4. Test the connection

ssh -T git@github.com

The first time, SSH asks you to confirm the host. Compare the fingerprint it shows with the one GitHub publishes (GitHub’s SSH key fingerprints; for Ed25519 it’s SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU), then type yes. Success looks like:

Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.

For the other hosts, run ssh -T git@gitlab.com (it answers “Welcome to GitLab, @username!”) or ssh -T git@bitbucket.org.

5. Clone the repository

git clone git@github.com:OWNER/REPO.git

Private repositories work the same way, as long as your account has access. git push, git pull and git fetch in that clone now use SSH too.

Switch an existing HTTPS clone to SSH

You don’t need to clone again. Point the remote at the SSH URL:

git remote -v
git remote set-url origin git@github.com:OWNER/REPO.git

Clone with a specific SSH key

SSH offers the keys in your agent and the default key files in turn, and GitHub accepts the first one that belongs to any account. With a personal and a work key, that is often the wrong one. Two ways to choose the key yourself:

One repository: GIT_SSH_COMMAND and core.sshCommand

Clone with the key you want:

GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes' \
  git clone git@github.com:company/project.git

Then save the setting in that repository, so later pulls and pushes use the same key:

cd project
git config core.sshCommand "ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes"

IdentitiesOnly=yes makes SSH offer only the key you named, not every key in the agent.

Several accounts: host aliases in ~/.ssh/config

# Personal GitHub account
Host github.com-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_personal
  IdentitiesOnly yes

# Work GitHub account
Host github.com-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

Clone with the alias in place of github.com:

git clone git@github.com-work:company/project.git

GitHub won’t let you add the same public key to two accounts (“Key is already in use”), so each account needs its own key.

SSH vs HTTPS

SSH HTTPS
Setup Generate a key, add the .pub to the host Sign in through a credential helper or create a personal access token
What sits on your machine A private key, ideally passphrase-protected A token, usually in a credential helper
Expiry GitHub keys last until you delete them; GitLab keys can expire Tokens usually carry an expiry date, and organizations can enforce a maximum
Several accounts Host aliases or core.sshCommand Separate credentials per host or path
Firewalls Port 22 is sometimes blocked; GitHub also accepts SSH on 443 Port 443, almost never blocked

GitHub stopped accepting account passwords for Git operations on August 13, 2021, so the real choice is an SSH key or a token. With SSH, only a signature crosses the network; a token can end up in shell history, CI logs or a remote URL. HTTPS with a credential helper such as Git Credential Manager is also a fine choice, especially behind strict firewalls.

Troubleshooting

Permission denied (publickey)

The server didn’t accept any key your machine offered. Check, in this order:

  1. Is the key on the right account? ssh -T git@github.com greets you by username. If it names a different account, SSH offered another key: use IdentitiesOnly as shown above.

  2. Does the agent have the key? ssh-add -l lists loaded keys. “The agent has no identities” means run ssh-add ~/.ssh/id_ed25519 again; this often happens after a reboot.

  3. Which key is SSH offering? Run the test verbosely and look for Offering public key and Server accepts key:

    ssh -vT git@github.com
    
  4. Are the file permissions too open? SSH ignores private keys that other users can read:

    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/id_ed25519
    

If ssh -T works but the clone says ERROR: Repository not found, the URL is wrong or your account has no access to that repository.

Host key verification failed

The host key in your ~/.ssh/known_hosts doesn’t match what the server sent. GitHub replaced its RSA host key in March 2023, so older machines still hit this. Remove the old entry, reconnect and check the fingerprint against GitHub’s published list:

ssh-keygen -R github.com
ssh -T git@github.com

Connection timed out on port 22

Some networks block port 22. GitHub accepts SSH on port 443 at ssh.github.com:

ssh -T -p 443 git@ssh.github.com

If that works, make it permanent in ~/.ssh/config, and your usual git@github.com: URLs keep working:

Host github.com
  Hostname ssh.github.com
  Port 443
  User git

Git keeps asking for the passphrase

The agent isn’t running or doesn’t have the key. On macOS, check the UseKeychain block from step 2. On Windows, Git for Windows ships its own ssh, which doesn’t talk to the Windows ssh-agent service; point Git at the Windows one:

git config --global core.sshCommand "C:/Windows/System32/OpenSSH/ssh.exe"

Frequently asked questions

Can I use the same SSH key for GitHub, GitLab and Bitbucket?

Yes. A key identifies your machine, so one id_ed25519.pub can go on all three. The one limit is within a host: GitHub won’t accept the same key on two different accounts.

How do I clone a private repository with SSH?

The same way as a public one: git clone git@github.com:OWNER/REPO.git. Your account needs read access to the repository. For a server that only needs one repository, add a read-only deploy key to that repository instead of a personal key.

What happens if I lose my private SSH key?

Delete its public key from every service where you added it (GitHub, GitLab, servers’ authorized_keys). That revokes access at once. Then generate a new key and add it.

Is an SSH key more secure than a password?

Yes. The private key never leaves your machine; the server checks a signature, so there’s nothing to phish or sniff. A passphrase protects the key file if your laptop is stolen.

Do I need a passphrase on my SSH key?

It’s optional but recommended. Without one, anyone who copies the key file can use it. With the ssh-agent or the macOS keychain, you type it once per session, not on every push. For more on what happens after the clone, see our guide to pulling and merging on GitHub.