Note that this applies only to ssh URLs, pushing to github or other sites that use the github trick (many do).
Where does my local machine obtain my user name when doing a git push? ... on github.com
It doesn't. Your local machine does not supply the user name.1 What your machine supplies to GitHub—and they then use—is a public key. More precisely, your local machine supplies at least one, and perhaps many, public keys; at least one of them must be registered at GitHub, and the first one that is registered, received, and working provides to GitHub the user name.
Note that for a public key to work, it must be registered in the first place, so that phrase has some redundant parts. It's still worth thinking about though. The process that ssh uses goes like this:
You run—or Git runs—ssh options user@host command
or similar: you can leave out the user@
part to imply that ssh should use the User
configured in .ssh/config
, or use your machine's user name, as the user name provided to the other machine. Since GitHub requires a literal git
here, well, see footnote 1. The command
part can be empty to imply that you'd like an interactive shell, but since GitHub demand a non-empty command that must be one of the allowed Git commands, that too is irrelevant. The options
part can include -i
options; it's possible to pass these through from Git, but not usually the way to go (see below).
Ssh resolves the host to an IP address and tries to dial that "phone number". Whoever answers requires some boilerplate protocol to set up acceptable key exchange algorithms and the like, which ssh supplies based on your ssh version and some configuration options. They (in this case GitHub) then provide their security fingerprint and other items so that ssh can verify that they are indeed who they claim to be (via .ssh/known_hosts
). Then the dance begins:
For each identity that ssh can offer to that host—the list of identities depends on both your ssh agent, if you have one running, and your .ssh/config
and any -i
options—your ssh will read the key-pair. It will offer the public key to them (GitHub). They will use that to encrypt a random string and send your ssh the encrypted data. Your ssh is then expected to decrypt this data and provide the original data back to them.
When your ssh is able to send back the original data, this proves that you hold the private key of that key-pair. That in turn proves that you are the person that the public key has, in the giant table over on GitHub of "this public key is Fred's, this one is Bob's, this one is Ramesh's, this one is Ilya's..."
That is who you are. You claimed indirectly to be that person, by offering that key and then successfully decrypting something.
I have two github accounts, each with their own public / private key pair. I learned earlier a public key can not be used for two accounts, that is why I have two pairs ... one for each account.
This is the critical bit that you left out of the original question. Because you have two keys, and both work, you must carefully select which one you present—or present first—to GitHub. It is easiest to select which one you present.
In your .ssh/cofig
file, you can list a number of fake-or-real host names and corresponding information. By using fake host names—gh-work
and gh-home
for instance—it's easy to get your ssh to offer only the work public key, or only the home public key. These are probably best shown by example. Here's a variant of what I have on my mac:
Host gh-work
Hostname github.com
User git
IdentitiesOnly yes
IdentityFile ~/.ssh/id.github.work.pub
Host gh-home
Hostname github.com
User git
IdentitiesOnly yes
IdentityFile ~/.ssh/id.github.home.pub
This means if I run ssh gh-work
, I'll have ssh offer, to GitHub, only the "work usage" key. If I run ssh gh-home
, I'll have ssh present only the "home usage" key.
Using the -i
flag, you can set the first key you'll offer. But using the IdentitiesOnly yes
and IdentityFile
lines, you can set the only key—or keys—you'll offer: the ones listed in the IdentityFile
lines for that Host
, in the order they are listed. (However, any -i
option key does get inserted before these, even with the IdentitiesOnly yes
, on at least some ssh implementations. Multiple -i
options seem to insert all the keys in that order.)
I've found that some ssh implementations require the private key file to be listed; the macOS one (with the agent running, which is a nice side effect of macOS login) allows the public key to be listed, and that's what I use on macOS and in this example. It should not hurt to list the private key file (ssh should always do the right thing) but out of general paranoia I prefer to list the public one if that works, and only switch to listing the private one if I have to.
1Technically, you must get your local machine to supply the user name git
. But since this is a required constant, we can ignore it here.