Pushing Git Changes without Typing Passwords
I'm lazy and use SSH public keys with my GitHub/GitLab repositories so I don't have to type a long password every time I push to one of my repos. This is a poor security practice, but let's document how it works anyway!
The short version: you upload a public key to your account settings on GitHub/GitLab. After that, these services will authenticate using that public key to check that you can prove you have the corresponding private key. If you do, then your git commands will run...no passwords typed!
The tricky part is determining why your SSH operations fail to work. It boils down to specifying WHICH KEYS ARE OFFERED and knowing how to SPECIFY THE CORRECT HOST URL, which is not as straightforward as you would think. There are two main concepts behind making it work:
-
The git
remote
is an alias for the URL of the repository you are tracking. This is set using thegit remote add <alias> <url>
command. For SSH the URL is the same format as a SSH login (e.g.git@gitlab.com:/path/to/repo/reponame.git
).Note that the usernane should begit
for both GitLab and GitHub, not your login name KEY: Thegitlab.com
in the connection string can refer to aHost
entry in SSH config. -
Your public/private SSH key pairs (aka "identities") are typically stored in your user directory at
~/.ssh
The files with.pub
extensions are your public keys, the ones without any extension are private keys. Don't share your private key! Don't forget to back them up when reinstalling the operating system! A program calledssh-agent
is loaded to "offer" a list of identities to the remote host, which will then try them one-after-the-other until it gets a response that PROVES you are indeed a valid user of the repository you're accessing. KEY: TheHost
entry in SSH config can be be told to offer a different identities even to the same domain (e.g.github.com
)
1. Choosing what identity keys are offered
The available key pairs ("identities") are stored in ~/.ssh
and referred to in the ~/.ssh/config
settings file. However, it is the helper program ssh-agent
that does the actual communication with a remote server to authenticate you before your git commands are allowed to run. This helper program usually runs automatically on computer startup.
When using the command line, ssh-agent
is initialized with a set of keys using the ssh-add ~/.ssh/keyname
command. This temporarily adds the identities you want to authenticate with. You also use this command to remove all identities with ssh-add -D
to start fresh. Finally, you can use ssh-add -l
to list all the currently loaded identities. To connect to different remote hosts with SSH, you use these commands to load/unload the proper identities for each.
Remember, though, that I'm choosing convenience over security. There are several shortcuts you can add by adding Host entries to the ~/.ssh/config
file.
2. Setting the correct Host
options
The Host entries in ~/.ssh./config
can be used as an address in an SSH connection string. This is super important, because it allows you to specify a particular IdentityFile to go with a particular HostName. Consider these two examples defined in the same config
file:
# address one
Host github.com
HostName github.com
User git
PreferredAuthentications publickey
IdentityFile /Users/dsri/.ssh/id_rsa
# address two
Host github.com-extra
HostName github.com
User git
PreferredAuthentications publickey
IdentityFile /Users/dsri/.ssh/github-ed25519
Note: At the time of this writing, the SourceTree git client adds its own entries to ~/.ssh/config
so you should review them, particularly when setting a git remotes for the first time with a new repo.
It is through the use of Host and the IdentifyFile that you create an alias for a particular connection. Note how both Host entries use the same user and HostName, but have different IdentityFile
settings.
You can use the command ssh -Tvvv <Host>
to debug the connection authentication and see which identities are being offered and tested; if you don't see the one you expect, your config might be goofed up. Remember, <Host>
refers to one of the Host
entries in ~/.ssh/config
!
ssh -Tvvv github.com
ssh -Tvvv github-extra.com
For further convenience, you can add the IdentitiesOnly
, UseKeychain
, and AddKeysToAgent
settings (the last tow are MacOS only):
Host github.com-second
HostName github.com
User git
PreferredAuthentications publickey
IdentityFile /Users/dsri/.ssh/id_rsa
IdentitiesOnly yes # use only IdentityFiles in this entry
UseKeychain yes # macos: store any passwords in apple keychain
AddKeysToAgent yes # macos: load this key to ssh-agent on startup
The MacOS settings are conveniences that would be handled in Linux or Windows differently.
3. Setting Git Repository Remotes
If you are using an SSH Host alias that is NOT just "github.com" or "gitlab.com", you MUST use change your remote URL accordinglycough SourceTree . For example, say you create a new repo on GitHub and want to add it as a remote to a local repo. GitHub provides instructions after you create the enw repo that look like this:
$ git remote add origin git@github.com:dsriseah/myrepo.git
$ git push -u origin main
$ git remote -v
Note: 'origin' is the name of the remote, and is an arbitrary convention much like the use of master
are used to refer to the "main branch" of a repo.
For remote add origin
line, the host here does not refer to the example config just above it. If my github.com-second
host alias is not the one I used with the github account, authentication will fail! The remote add
has to be changed to:
$ git remote add origin git@github.com-second:dsriseah/myrepo.git
Command Cheat Sheet
Using ssh-agent
and ssh-add
eval ssh-agent # run the ssh agent if it's not already running
ssh-add ~/.ssh/keyFile # load identity for 'keyFile'
ssh-add -l # list loaded identities
ssh-add -D # unload all identities
ssh -T domain.com # test if can connect with current config
ssh -Tvvvv domain.com # add a ton of debug output