How to change a Git repository from HTTPS to SSH

I seemed to spend a crazy amount of time trying to work out how to change access to a Git repository (repo) from HTTPS to SSH to avoid password prompts when pushing changes to BitBucket and GitHub. Here, I outline how to do it on Mac OS X, partly to remind myself how to do it in the future, partly to collate all the infomation on the internet about it and partly in the hope that someone else might find it useful.

This rigmarole needs to be done on each computer you intend to access your Git repo with for each repo you have that you want to access by SSH rather than by HTTPS.

Change the remote path of the repo

This is how you tell your Git server how you want to access it.

Open Terminal or your command-line app of choice and navigate to your repo’s directory:

cd ~/projects/reponame

then check to see what you have on your server already:

git remote -v

You should see a pair of entries for each remote repo (I once had origin and origin2, but that’s another story): one for fetch, which includes pull, and one for push:

origin  https://[email protected]/username/reponame.git (fetch)
origin  https://[email protected]/username/reponame.git (push)

This example shows a repo on BitBucket; GitHub is similar. You can see that the URLs include the https:// protocol. This is what we want to change. Type the following for BitBucket:

git remote set-url origin [email protected]:username/reponame.git

For GitHub, replace bitbucket.org with github.com. Then check what’s there again:

git remote -v

This time, you’ll see something like this:

origin [email protected]:username/reponame.git (fetch)
origin [email protected]:username/reponame.git (push)

Troubleshooting

Error: Could not resolve hostname

You might get this error:

ssh: Could not resolve hostname github.com:username: nodename nor servname provided, or not known
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

If you do, check the output from git remote -v carefully. See if the SSH URL is prefixed with ssh://, like this:

origin ssh://[email protected]:username/reponame.git (fetch)
origin ssh://[email protected]:username/reponame.git (push)

If it is, run set-url again, making sure to exclude the ssh:// part of the URL. Run git remote -v again and check the output. You may find that only fetch has changed — if so, the next section should help.

Only fetch changes; push stays the same

If the fetch URL has changed but the push URL has not, like this:

origin [email protected]:username/reponame.git (fetch)
origin https://[email protected]/username/reponame.git (push)

or like this:

origin [email protected]:username/reponame.git (fetch)
origin ssh://[email protected]:username/reponame.git (push)

you’ll need to do the push separately by using the --push option:

git remote set-url --push origin [email protected]:username/reponame.git

You don’t need to do anything further for pull because it does what fetch does (because pull is equivalent to fetch then merge).

I don’t know why it works for some cases but not other ones. It happened for me when I got the could not resolve hostname error above and ran set-url again. It seems that the set-url command is applied to both fetch and push when changing the protocol, but when keeping the (SSH) protocol the same, it only updates fetch.

If you have a SSH key already for the computer/device you’re using, you’re all set. If not, read on.

Create a SSH key

If you don’t already have a SSH key for BitBucket and/or GitHub on the particular device you’re using, you’ll need to create one for each service that you use and on each device that you will use to access your repos:

You’ll end up with two SSH keys, one private and one public, which you can see by running:

ssh-add -l

or you can list all the SSH keys you have by running:

ls ~/.ssh

which will output something like:

id_rsa
id_rsa.pub

The key without the extension is the private key and the key with the .pub extension is the public key. The private key stays on your computer and the public key is uploaded onto the server.

BitBucket recommend you keep the default key name [id_rsa] unless you have a reason to change it. However, I’d recommend using something descriptive, like bitbucket_id_rsa so you know what it’s for later and to avoid accidentally overwriting the key if you create one for BitBucket, one for GitHub, one for your web server and so on.

Add the public SSH key to your remote Git server

The public SSH key (the one with the .pub extension) is for the server, so you need to upload it to your account on the relevant one:

Add the private SSH key to your keychain

If you don’t add the SSH key to your keychain, you’ll have to keep entering the passphrase you set up when creating the SSH key.

  1. Start the SSH agent in the background:
    eval $(ssh-agent)

    which gives you an agent pid:

    Agent pid: 12345
  2. Add the private SSH key (the one with no extension) to your keychain; the -K option is Mac-specific and is what tells your Mac to add it to the keychain as well as wherever else it adds it to:
    ssh-add -K ~/.ssh/github_id_rsa
  3. For MacOS Sierra onwards, you must add the SSH key file to the ~/.ssh/config file so you don’t have to call the previous command every time you restart your Mac. This also seems to be what makes the whole thing work with Sourcetree.
    1. Create a config file in your SSH keys directory, if there isn’t one already (you can check by using ls ~/.ssh):
      nano ~/.ssh/config

      I prefer the Nano editor if I’m going to use a command-line editor, but you can use Vim or Emacs or whatever you like, of course.

    2. Add an entry for Host * (where * means any host, I presume) stating that the keychain is to be used and the keys are to be added to said keychain. An IdentityFile entry in your ~/.ssh/config file is needed for each SSH key:
      Host *
      AddKeysToAgent yes
      UseKeychain yes
      IdentityFile ~/.ssh/bitbucket_id_rsa
      IdentityFile ~/.ssh/github_id_rsa

      If you don’t add this config file, you’ll have to run ssh-add -K ~/.sshkeyname every time you restart your Mac.

  4. You should now be able to use Git without having to use your password all the time.

Test it works

You can type in the terminal for a GitHub repo:

ssh -T [email protected]

to get the following message:

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

For a BitBucket repo, type:

ssh -T [email protected]

to get the following message:

logged in as <username>.

You can use Git or hg to connect to Bitbucket. Shell access is disabled.

In your terminal, assuming your repo is up-to-date, you can test everything works by typing the following:

git fetch

which should give no output if it works. Typing:

git push

should result in an up-to-date message:

Everything up-to-date

If that works, try pressing Fetch in Sourcetree then Push. If you get no errors, you’re good to go.

Troubleshooting

Warning: Permanently added the RSA host key for IP address ‘xxx.xxx.xxx.xxx’ to the list of known hosts

This warning seems to be merely an informative message. You shouldn’t see it again and you can quite happily ignore it.

Error: Permission denied

If you get this error, especially in Sourcetree:

[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

then check that you have spelt everything correctly and followed every step.

Bibliography

Listed in no particular order, the following links helped me get all this working and/or contain more information that might help you understand what’s going on:

I am very grateful to all the people who contributed to getting this information out there for me to find. Thank you.

Update: I’m delighted to hear that collating this information has helped other people sort out their configurations – thank you for letting me know in the comments 🙂

15 thoughts on “How to change a Git repository from HTTPS to SSH

    1. That’s great, Dieter! I’m glad I could help someone else 🙂 Thank you for taking the time to tell me.

  1. Thank you so much, I wanted to “migrate” my repos to ssh, and this was exactly what I was looking for!

  2. Thanks, this is still useful!
    My server changed IP address, so I was looking to fix “Warning: the RSA host key for ‘example.com’ differs from the key for the IP address ‘xxx.xxx.xxx.xxx'”.
    I deleted both the ‘offending’ and ‘matching’ lines from the ~/.ssh/known_hosts file and that allowed the system to ‘permanently add the RSA host’.

  3. Thanks – this was really useful – Github has changed up their authentication so I’ve had to move away from password on CLI and ssh is the lightest way to go. Cheers

    1. Hi Ingram, you’re most welcome! I’m really pleased I could help you solve your problem. Thanks for letting me know 🙂

    2. I’ve recently come across this situation myself in a repo I hadn’t used for a while. I wasn’t sure how to use the application password they recommend with iTerm, but then I remembered your comment about using SSH instead. Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.