Reputation: 29109
I'm trying to clone a repo, lets say that the url is example.com/my-code
and my username is john@foo
. Now, the problem is, when I do
$> git clone example.com/my-code
[email protected]'s password:
which is is an incorrect username!
I tried to provide the username in the url
$> git clone john@[email protected]/my-code
john@[email protected]'s password:
Even when I use -v
it ask me for a password directly. So, my question is, how can I provide it a different username? Via the url is find, but I prefer the CLI. thnx
Upvotes: 3
Views: 10008
Reputation: 4162
Why john@foo@
? Should be john@
only in this case, or foo@
only.
Otherwise use git@
, which is a common username for GitHub and GitLab. It will use your SSH credentials.
If you have a GitHub or GitLab Repository, the SSH URL can be seen there. You don't have to change the username.
Make sure to add your public key to your profile settings!
If you are talking about username/email, read below as well.
To configure your user and/or email adress globally, use this:
$ git config --global user.name "Example Name"
$ git config --global user.email "[email protected]"
To set the user and email for the current repository you do the same as above, but remove the --global
flag.
$ git config user.name "Example Name"
$ git config user.email "[email protected]"
To have a certain user and/or email adress you can change the configuration for one call only:
$ git -c user.name="Example Name" -c user.email="[email protected]"
Upvotes: 1
Reputation: 487993
You'll want to set up your ssh configuration. See below.
URL (or more properly, URI) syntax in general is:
<scheme>:[//<authority>]<path>[?query][#fragment]
as described more properly here on Wikipedia. When using ssh
URLs, the scheme
is ssh
, and the colon :
and slash-slash //
are followed by user@host
and another slash:
ssh://[email protected]/user/repo.git
for instance. This avoids the need for interaction: the user name is supplied right in the command. There is no need for a password as ssh uses public-key encryption, though there may be the need to supply a passphrase to gain access to the private key, in some setups. This means ssh can work without human interaction, which is important for automatic computerized updating. (We'll come back to this more below.)
To use an HTTPS URL, on the other hand, you'd normally write:
https://github.com/user/repo.git
because HTTPS authentication generally happens interactively. So this starts with the assumption that the system can pop up an authentication interactor of some sort, in which the user types in the user name and token-or-password.
A URI can accommodate a user name (and even a plain-text password) in both cases, but the expected use cases are different: that ssh doesn't require a user with hands and eyeballs, while http(s) does. So that's why the defaults differ.
It's also worth noting here that Git itself does not get its grubby little paws any dirtier with authentication by shoving the authentication piece off to either another program entirely (ssh) or a library (libcurl) and separate credential helper (external program) for https). By doing this, it leaves the details up to the OS, as ssh, libcurl, and various credential helpers are customized for each OS.
Git has its own special pseudo-URL syntax:
[user@]host:path
is shorthand for:
ssh://[user@]host/path
which matches how command-line ssh takes its optional-user-and-host parts.
You can automate some or all things with https by selecting an appropriate (to your OS) credential helper. Since they vary so much from one OS to another, it's complicated. Ssh is simpler, if only because it has spent less time diverging on different OSes (though even then it can get complicated).
It's important to understand how ssh works here, at least at a high level. (You don't need to know all the details of key exchange operations unless and until things start going wrong.) The ssh system "wants" to be secure, and that means not only guaranteeing to, say, GitHub, that you are in fact you, but also guaranteeing to you that the machine you've connected to, thinking it's GitHub, really is GitHub.
The latter works through a system often abbreviated TOFU, or Trust On First Use. This is quite different (and simpler) as compared to HTTPS/SSL (which uses certification authorities and chains-of-trust instead of TOFU): the first time you have your computer call up GitHub's computer, GitHub's computer offers your computer a secret. Your computer says "Huh, this is the first time I've seen this. Would you like to trust them to be who they say they are?" Specifically:
The authenticity of host ... can't be established. ...
Are you sure you want to continue connecting (yes/no)?
If you say "yes", ssh will by default record the secret and the next time you call up the same host and they offer the same secret, believe you're calling up the same host. This works pretty well in practice. (You can tweak this setting but it's usually good to let it do its thing.)
Having decided that, say, github.com are who they claim to be—that you didn't get usurper.evil instead due to some weird glitch—your ssh now tells their ssh that you would like to log in as some user name on their host. Here's where Git gets a little weird, because most hosting servers have everyone in the universe log in as user git
.
To make this happen, you can either write git@host
every time you set up a URL, e.g., ssh://[email protected]/user/repo.git
, or you can use your ssh config file—found in ~/.ssh/config
or $HOME/.ssh/config
or similar, depending on your OS and shell—to make git@
the default for that host or some set of hosts. That way, if you don't provide a user name—if you just ssh github.com
for instance—your ssh will provide the user name git
. To do this, you would write:
Host github.com
User git
in your .ssh/config
.
But if you're claiming to github.com to be user git
, how will github.com know who you really are? This is where the public and private key part comes in.
It's worth a sidebar paragraph here to mention that ssh doesn't have to use a public-key here. You can log in to some host using the "keyboard interactive" method. Here you supply the correct user name in the user@host
part, and they ask your ssh to supply the password. Your ssh reads a password from you, encrypts it with a session key so that it's not going out as cleartext, and they decrypt it with that key and try it. But for Git's use with GitHub we never use this method in the first place.
To use a public/private key pair, you will need to run ssh-keygen
before you even start trying to use ssh to communicate with GitHub. The ssh-keygen
program takes a number of optional parameters and these vary somewhat with your ssh release and OS, so consult the appropriate documentation for details. The output from ssh-keygen is one of these key pair things though: there's a public key, which you can give to anyone, and a private key, which, well, you keep private.
Your public key goes into a file whose name ends with .pub
, e.g., ~/.ssh/id_rsa.github.pub
if you store a particular GitHub-only key in a file (as I do). This file has one fairly long line in it that will start with ssh-rsa
or ecdsa-sha2
-something or something along those lines. It generally ends with the email address you told ssh-keygen
to put in it (though this email address is purely informational).
Your private key goes into another file with the same name but without the .pub
ending. This file is much longer and consists of many shorter lines, beginning with, e.g., -----BEGIN RSA PRIVATE KEY-----
if it's an RSA key. This key you keep to yourself: it's a secret.
You now log in to GitHub via their web pages and a web browser, using your GitHub account and GitHub password (not any public/private key stuff from ssh) and navigate to the pages where you store your ssh keys on GitHub. You then enter your public key here. See also here and here in the GitHub documentation; note that GitHub do some magical browser detection to try to give you OS-specific directions, which doesn't always work, so sometimes you might need to click on a Mac/Windows/Linux selector to get the instructions for the OS you intend to use, rather than the one you're browsing from.
To claim, to GitHub, to be you, you have your ssh send, to GitHub, the public key that you stored on GitHub earlier. Because public keys are very large and yours won't match anyone else's, GitHub can simply look to see who gave them this particular public key earlier. That's who you're claiming to be. But, because this is a public key, GitHub cannot yet trust that you really are the person you're claiming to be. So GitHub now make up a secret—a collection of randomized bytes—and send those to you after using this public key to encrypt the bytes.
If you can decrypt the bytes easily, that implies that you have the private key. Without the private key, doing this decryption would—at least in theory—take many years of compute time at best. So if your computer can repeat the bytes back to GitHub, you must in fact be you, in possession of the private key that goes with the public key you sent.
This is how GitHub know who you are. You are you because:
You have both parts of the keypair: you are who you claimed to be earlier when you sent the public part. You made this claim simply by sending the public part: GitHub ignores (well... effectively ignores) the git@
part of [email protected]
(but you still have to send it).
Some people have a need to authenticate, to a single web hosting system such as GitHub, as two or more different identities. For instance, it's pretty common to have a "work ID"—a corporate identity, as it were—and a "personal ID" and to want to access work-related repositories using the work ID, while accessing personal repositories using the personal ID.
There is an easy way to do this with ssh, using ssh's "fake host name" convention. You still generate normal key-pairs as usual, but you have your ssh-keygen
save them in files with easily distinguished names, such as:
.ssh/id_rsa.github.work .ssh/id_rsa.github.work.pub
.ssh/id_rsa.github.play .ssh/id_rsa.github.play.pub
You then install both of the public keys on GitHub, on two different accounts: the "you" for work and the "you" for play. Now you need to get ssh to offer the right key.
Ssh has the ability to try more than one key, so that's one way to deal with this. It's not really the right way though as it means you can accidentally use the wrong key-pair, which if nothing else generally shows up in security logs and alarms security people. (GitHub's operators probably won't care, but if you use this same technique with a corporate server, they may care.) You can also wind up triggering attack-deflection software: if you come up to a server, brandish a million keys, and start trying all of them, the server software might decide you're no good and divert you off to a fake system that keeps you occupied while trying to track you down. So, ideally, you should just have your ssh offer the right key. And you can do this pretty easily!
In your .ssh/config
file, you can list:
Host gh-work
Hostname github.com
User git
IdentityFile ~/.ssh/id_rsa.github.work.pub
IdentitiesOnly yes
Host gh-play
Hostname github.com
User git
IdentityFile ~/.ssh/id_rsa.github.play.pub
IdentitiesOnly yes
for instance. Here you're saying to ssh that if you run ssh gh-work
, ssh should instead connect to github.com
, attempt to log in as user git
, and provide only the identity in ~.ssh/id_rsa.github.work.pub
. (Depending on your ssh setup and other items you may have to list the private key file here instead of the public key file. Try the public key file first.) Similarly, if you run ssh gh-play
, ssh should connect to github.com
as before but this time use the "play" identity.
You now just need to configure your Git repositories with faked URLs:
git clone ssh://gh-play/me/myrepo.git
to clone your "play user" repository, and:
git clone ssh://gh-work/corp/corprepo.git
to clone some corporate "work" repository. The URL for the repository controls who you claim to be; who you claim to be controls whether you have access; and once you have the repository cloned, you have the desired URL stored in the name origin
from then on, so everything just works.'
Note that when using ssh-keygen
, you must use the real host name—in this case, github.com
—and not the fake name like gh-work
or gh-play
. The ssh-keygen code does not read the .ssh/config
file and has no idea that gh-work
stands in for github.com
.
Running:
ssh -Tv [email protected]
or:
ssh -Tv gh-play
will, for instance, test out the ssh part of the process. Git is not involved here. The -v
option tells ssh to print verbose debug messages, so that you can observe the keys going over to github (or wherever). This initial test also serves to record the host fingerprint in your ~/.ssh/known_hosts
file, so that future connections that Git makes won't ask if you trust GitHub to be GitHub.
The -T
option (and the -v
option, for that matter) is not really necessary: it just tells your ssh that there's no need to attempt to use a pseudo-teletype, which will avoid certain error messages. If all goes well, GitHub print a message of the form:
Hi _______! You've successfully authenticated, but ...
(with the blank filled in and the ...
fleshed out). The filled-in blank shows the GitHub account that your ssh keypair successfully claimed to be.
If things don't go well here, the debug output from -v
can help figure out why. Note that it's pretty long; if it's not long or detailed enough, -vv
or -vvv
makes it even longer and more detailed.
To use ssh with GitHub or similar:
ssh -Tv [email protected]
or similar to test it out. Different hosting sites have different ways to tell you whether this worked; most will have some way to tell you.git clone
with ssh URL(s) containing the host name(s) you've chosen to use to gain access to the hosting site using the ssh ID(s) you set up. Remember that you can only clone existing repositories here; if you need to make a new repository on a hosting site, you must usually do that through their web interface.Be sure to use ssh URLs. These start with ssh://
, or you can use the user@host:path/to/repo.git
syntax if you prefer, but this just saves you from typing six letters once; compare ssh://github.com/me/repo.git
(28 letters) to github.com:me/repo.git
(22 letters). Once you've entered the URL once, you'll just use origin
from then on (six letters).
Upvotes: 1