# Setup Git for Multiple Git Servers

Company I worked at using self-hosted gitlab, while I'm using github for personal works. I interact with git servers using ssh-based method so I need to generate SSH Key as git identification method. I just can just generate one `~/.ssh/id_rsa` file as usual but I want to use different keys for different git servers.

I don't know how it will affect security, but I want to use different for each one. Here I will show how to utilize SSH Config to achieve this.

## Configure SSH
Let's say we have these two git accounts:

| Server | Name | Email |
|---|---|---|
|`Gitlab`|`John Doe`|`john.doe.work@something.io`|
|`Github`|`John Doe`|`john.doe.personal@gmail.com`|

First, we need to create SSH Keys for these account. We may generate keys as many as we want. File permission with code `600` means you and only you that can read and modify this files.


### Creating necessary files and directory
1. We should create a directory where SSH will look for our keys. By default it will stored in `~/.ssh`, so if this directory doesn't exists we need to create it first. The easiest way is to use `mkdir ~/.ssh` command.

2. Next we need to store our SSH config somewhere. Usually SSH configuration stored `~/.ssh/config`, under the directory we just created. Create the file if it's not exists yet, can be using `touch ~/.ssh/config`. We'll secure this file using `chmod` with `600` file permission.

So complete commands would be:
```shell
mkdir ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config
```

Now, we want to generate SSH keys using `ssh-keygen`. The key will be 4096 bit long so we should add `-b 4096` argument. Choose key name to your liking, in this example we will use key `id_rsa_personal`. And same as the `config` file we need to set permission for generated keys using `chmod.`

```shell
# Generate SSH Keys for personal
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_personal
chmod 600 ~/.ssh/id_rsa_personal
chmod 600 ~/.ssh/id_rsa_personal.pub
```

Repeat this step to generate key for work, just replace the key name e.g. `id_rsa_personal` to `id_rsa_work`.

Now, `~/.ssh` directory should have required files, try running `ls -la ~/.ssh` and we should see 5 files:
1. `config`
2. `id_rsa_personal`
3. `id_rsa_personal.pub`
4. `id_rsa_work`
5. `id_rsa_work.pub`


Copy public keys content to your git server profile, set the title to be useful to identify which device you generate these keys:
- [https://github.com/settings/ssh/new](https://github.com/settings/ssh/new)
- [https://gitlab.com/-/profile/keys](https://gitlab.com/-/profile/keys)

You can use `pbcopy` to copy file content to clipboard, you can do `paste` on your git server SSH setting page. 
```shell
pbcopy ~/.ssh/id_rsa_personal.pub
```
> Remember to only copy the public key content, the one eith `.pub` file extensions, the other file is your secret key and you need to keep it secure and not share it to anyone.


## Configure Git

Until this, we we wont be able to interact with git server because git will confuse which key to use. We need to configure git which we will explore in the next section.

### Load different SSH Keys for different Git server
Now we need to tell the git on our machine which keys it needs to use when interacting with which git server. Open file `~/.ssh/config` in your favorite text editor and add these line. Save the file.

```ini
Host gitlab.com
    HostName gitlab.com
    IdentityFile ~/.ssh/id_rsa_work

Host github.com
    HostName github.com
    IdentityFile ~/.ssh/id_rsa_personal
```

Now we can perform git operation to Github or Gitlab since git now knows which keys to use.

### Load different SSH Keys for different Git server

We already setup the git identification with SSH method. Now we want to configure git to use different account on each interaction, the most important one is `commit`. When you do commit, git will record name and email of the comitters. Here is example of `git log` output, notice the Author is `user.name` and `user.email` combined.
```txt
commit f471c512e3413ffe6ed8d2ccd6403c50eccac58b (HEAD -> master)
Author: John Doe <john.doe.work@something.io>
Date:   Tue Sep 28 09:41:49 2021 +0700

    Commit message here.
```

Since we have different emails for each git servers, we don't want to commit to work projects using personal information, or vice-versa. We can configure git to use different account on each directory. Say we can organize our project such as:
1. `~/work`, and
2. `~/personal` respectively.


### Separate git configuration for work and personal

The plan is to create separate config into files, and the tell git to load them based on where the git command called from. Create 2 files in home directory.
1. `~/.gitconfig-personal`
2. `~/.gitconfig-work`

The content of each file should reflect your git credentials, for example the content of `~/.gitconfig-personal` in this example would be:
```ini
[user]
name = John Doe
email = john.doe.work@gmail.com
```

Do the same with `~/.gitconfig-work` and fill your work git `user.name` and `user.email`.


Git reads configurations from `~/.gitconfig` file, not from the 2 files we just created, unless we tell git. Create the files if it doesn't exists using `touch ~/.gitconfig`. Edit the file and put the following lines.
```ini
[includeIf "gitdir:~/personal/"]
  path = .gitconfig-personal
[includeIf "gitdir:~/work/"]
  path = .gitconfig-work
```

The file content is self-explanatory. But just to make sure we understand, I'll explain. This tells git if we run `git` from any directory under `~/personal/`, says `~/personal/my-blog`, git will use `~/.gitconfig-personal` file and use the content inside when doing operations e.g. to set Name and Email of commits.


## Summary
In my personal experience, it is fairly easy to mixed git account when pushing changes. On my machine, I set global git to use my personal git account. Meanwhile related to work, as soon as I pulled new repository, I need to update git config for that project to not use my personal git. But people forget, several times I pulled a repo and pushed to work project using my global git account which is my personal info. Git won't care about this, but not with Gitlab and Github. Your work/commits will not appear in these website if you put wrong account when doing commit.

This workaround have been working for me so well and I don't worry anymore about committing my changes using different account.

## Resources
- [File Permission 600](http://www.filepermissions.com/file-permission/600)
- [SSH Key Permissions chmod settings?](https://unix.stackexchange.com/questions/257590/ssh-key-permissions-chmod-settings)
- [Can I specify multiple users for myself in .gitconfig?](https://stackoverflow.com/questions/4220416/can-i-specify-multiple-users-for-myself-in-gitconfig)
