This is an SSH error, not a Git one. Git asked SSH to open a connection, SSH offered whatever keys it had, the server rejected all of them, and Git reported the failure it was handed.
That distinction matters because it tells you where to look: nothing about your repository, your branch or your remote URL is relevant yet.
Prove what is actually happening
ssh -T git@github.com
Hi alice! You've successfully authenticated, but GitHub does not provide shell access.
That message is success. GitHub has no shell, so this is as far as it goes. If you see it, SSH works and the problem is elsewhere.
If it fails, get the detail:
ssh -vT git@github.com 2>&1 | grep -E "Offering|Authentications|identity file|Server accepts"
debug1: identity file /Users/alice/.ssh/id_rsa type -1
debug1: Offering public key: /Users/alice/.ssh/id_ed25519 ED25519 SHA256:Xy3k...
debug1: Authentications that can continue: publickey
Two lines tell you nearly everything. Offering public key shows which keys SSH tried, if nothing is offered, that is your answer. type -1 means the file named does not exist.
Cause 1: No key is being offered
The most common case, and the debug output makes it obvious: no Offering public key line at all.
ls -la ~/.ssh/
-rw------- 1 alice staff 411 16 Sep 09:14 id_ed25519
-rw-r--r-- 1 alice staff 101 16 Sep 09:14 id_ed25519.pub
If there is no key, create one:
ssh-keygen -t ed25519 -C "alice@laptop"
Then add the public key, the .pub file, to your account. Never the private one:
cat ~/.ssh/id_ed25519.pub
SSH only offers default filenames automatically (id_ed25519, id_ecdsa, id_rsa). A key named github_key is not tried unless you tell SSH about it. See the config section below.
Cause 2: Wrong permissions on the key
Permissions 0644 for '/Users/alice/.ssh/id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
SSH refuses to use a private key other accounts can read, and ignores it silently as far as Git is concerned. You just see Permission denied (publickey).
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
This appears most often after copying keys from a backup, another machine, or a mounted volume, all of which lose the original modes.
Cause 3: The agent has no identities
ssh-add -l
The agent has no identities.
ssh-add ~/.ssh/id_ed25519
On macOS, persist it across reboots:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
And in ~/.ssh/config so it happens automatically:
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
On Linux, the agent is usually started by your session. If ssh-add -l reports Could not open a connection to your authentication agent, start one:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
Cause 4: The key is not on the account, or on the wrong one
The key exists, has correct permissions, is loaded, and the server still rejects it. Compare fingerprints:
ssh-keygen -lf ~/.ssh/id_ed25519.pub
256 SHA256:Xy3kQ9mP4vL8nR2tF6wH1jC5bN7dS0aZ MD5:... alice@laptop (ED25519)
That fingerprint must appear in your account's SSH keys list. If it does not, the public key was never added, or was added to a different account, which is easy on a machine with both personal and work identities, and produces exactly this error against one host while working against another.
ssh -T git@github.com
ssh -T git@gitlab.com
Testing both quickly shows whether the key works somewhere.
Multiple accounts, multiple keys
The clean solution is a host alias per identity in ~/.ssh/config:
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
git clone git@github-work:acme/orders-api.git
git remote set-url origin git@github-work:acme/orders-api.git
IdentitiesOnly yes is the important line. Without it SSH offers every key it knows about in turn, and the server accepts the first valid one, which may be the wrong account entirely. That produces the confusing situation where a push "works" but commits arrive under the wrong identity, or where the server rejects you after too many failed offerings.
Check the remote is actually SSH
git remote -v
origin git@github.com:acme/orders-api.git (fetch)
origin https://github.com/acme/orders-api.git (push)
A mismatched pair like that fetches over SSH and pushes over HTTPS. If you meant SSH throughout:
git remote set-url origin git@github.com:acme/orders-api.git
Note that Permission denied (publickey) only ever comes from the SSH form. An HTTPS remote fails with a credential prompt or a 403 instead, which is a different problem entirely.
When the key is right and it still fails
Two less common causes worth knowing.
The repository does not exist, or you lack access. The message deliberately conflates "no such repository" with "no permission", so a private repository you are not a member of looks identical to an authentication failure. If ssh -T succeeds but git clone fails, this is why.
The organisation requires SSH certificate authority or key expiry. Some organisations expire keys or require SAML SSO authorisation per key. In that case the key is listed on your account and still rejected until authorised.
A checklist
ssh -T git@github.com. Does SSH itself work?ssh -vT git@github.com. Is any key being offered?ls -la ~/.ssh. Does the key exist, and is it600?ssh-add -l. Is it loaded into the agent?ssh-keygen -lf ~/.ssh/id_ed25519.pub. Is that fingerprint on the account?git remote -v. Is the remote actually SSH?- Multiple identities → host aliases with
IdentitiesOnly yes. - SSH works but clone fails → repository access, not authentication.
Frequently Asked Questions
What does "Permission denied (publickey)" actually mean?
That the SSH server rejected every key your client offered. It is an SSH failure that Git is merely reporting, so nothing about your repository, branch or Git configuration is involved yet. Run ssh -T git@github.com to test SSH on its own, if that succeeds, authentication is fine and the problem is repository access instead. ssh -vT shows which keys were offered, which is usually enough to identify the cause in one command.
Why does SSH ignore my key even though it exists?
Most likely its file permissions are too permissive. SSH refuses to use a private key that other accounts on the machine could read, and skips it, so from Git's perspective no key was offered at all. Run chmod 600 ~/.ssh/id_ed25519 and chmod 700 ~/.ssh. This appears most often after copying keys from a backup, another machine or a mounted drive, since all of those lose the original file modes.
Why isn't my key with a custom filename being used?
Because SSH only tries default names automatically, id_ed25519, id_ecdsa, id_rsa. A key called github_work is invisible to it unless you either add it to the agent with ssh-add or name it in ~/.ssh/config with an IdentityFile entry. The config approach is better, since it survives reboots and documents which key belongs to which host.
How do I use different SSH keys for work and personal GitHub accounts?
Define a host alias per identity in ~/.ssh/config, each with its own IdentityFile and IdentitiesOnly yes, then clone using the alias, git@github-work:acme/repo.git. The IdentitiesOnly yes line matters: without it SSH offers every key in turn and the server accepts the first valid one, which may authenticate you as the wrong account, so commits land under the wrong identity or the server rejects you after too many attempts.
How do I check whether my key is on my GitHub account?
ssh-keygen -lf ~/.ssh/id_ed25519.pub prints the key's fingerprint, and that exact string should appear in your account's SSH keys settings. If it is absent, the public key was never added, or was added to a different account, which is easy to do on a machine holding both work and personal identities and produces this error against one host while another works fine.
SSH authenticates successfully but git clone still fails. Why?
Because the message conflates authentication with authorisation. Once ssh -T succeeds your key is fine, so a failing clone means the repository does not exist at that path, or your account cannot see it. A private repository you are not a member of looks identical to an authentication failure by design, so as not to reveal which repositories exist. Check the path carefully, and whether your key needs SAML SSO authorisation for that organisation.