GitHubアカウントを同PCで使い分けるときにはIncludeIfを使おう！

## はじめに

諸事情あり、GitHubのアカウントを同じPCで2つ使い分ける状況になりました。
その際に調査してみつけた.gitconfigのIncludeIfがとても便利だったので設定例とともに共有します！

## 最初に行ったこと

.gitconfigの設定例の前に自分が最初に行ったことのご紹介です。

### 1. 鍵の新規生成

異なるgithubアカウントに同じssh鍵を登録することができないので、新しいkeyを生成します。

```
ssh-keygen -t rsa

>> Generating public/private rsa key pair.
>> Enter file in which to save the key (/Users/user/.ssh/id_rsa): id_rsa_account2
>> Enter passphrase (empty for no passphrase):
>> Enter same passphrase again:
```

生成してくれた公開鍵をsettings -> SSH and GPG keysに登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622760/99d6f8c6-0ce2-e443-7b05-f4b8b1ef40b2.png)

### 2. ~/.ssh/configへの追記

続いてこのキーを使うアカウントを指定するために~/.ssh/configへの記載を行います。

```
Host account1
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_account1

Host account2
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_account2
```

実はここまでの設定だけでもアカウントの使い分けができます。
sshコマンドで確認してみます。

```
ssh -T account1 # configで設定したhost名
>> Hi {account1でのuser name}! You've successfully authenticated, but GitHub does not provide shell access.

ssh -T account2 # configで設定したhost名
>> Hi {account2でのuser name}! You've successfully authenticated, but GitHub does not provide shell access.
```

### このままだと不便なこと

ひとことで言ってしまえばリモートリポジトリ名の変更です。

これまでgithubで管理していたリモートリポジトリは

```
git@github.com:<ownerName>/<repoName>.git
```

のようになっていると思いますが、`@`以降の`github.com`はhost名の指定になります。
先ほどhost名を修正してしまったためリモートリポジトリの指定も以下のように修正する必要があります。

```
git@account1:<ownerName>/<repoName>.git
```

この若干の手間がかかる修正だけで済めばまだよいのですが、
account1で設定している秘密鍵の名称を`id_rsa`などのデフォルトの名称で設定している場合は、その鍵を使った接続が優先されるようで、
ホスト名を`github.com`のままにしても`account1`の認証をつかった接続が実行されてしまいます。

そのため、2つのアカウントに同じリポジトリ名を持ったものがある場合、間違って意図しない方へpushしてしまう可能性もでてきちゃって怖いなと思いました。

そんな心配性かつめんどくさがりな自分のための設定が以下に説明するIncludeIfの設定です。
## .gitconfigへIncludeIfの設定

IncludeIfはひとことで言うと、指定したローカルディレクトリの中でgitconfigの上書きができる設定です。

ですので、account2で管理しているリポジトリ用に新たにディレクトリを作成し、その配下で管理するようなディレクトリ構成に変更する必要があります。
今回は`~/account2/`というディレクトリでaccount2のリポジトリを管理するという例にしてみます。

```
~/account1/ #アカウント1で管理しているgitリポジトリ
~/account2/ #アカウント2で管理しているgitリポジトリ
```

ディレクトリの設定が完了したら、下記のように`~/.gitconfig`にincludeIfの追記を行います。
`gitdir`には設定したディレクトリ、`path`にはこの内部で上書きさせる設定値を管理するファイルのパスを指定します。

`gitdir` で指定するディレクトリの末尾には`/`を必ずつけるようにしてください。
自分はこれのせいで思うように設定が適用されず30分くらい
「gitconfig  includeif not work」とかでググることになりました..

```diff:.gitconfig
[user]
  name = account1_user
  email = account1@sample.com
  signingkey = "~/.ssh/id_ed25519.pub" #設定している場合
[gpg]
  format = ssh #設定している場合
[gpg "ssh"]
  allowedSignersFile = /Users/user/.ssh/allowed_signers #設定している場合
[commit]
  gpgsign = true #設定している場合
[alias]
  st = status
  f = fetch
  rb = rebase
  co = checkout

+[includeIf "gitdir:~/account2/"]
+  path = ~/.gitconfig_account2
```

### .gitconfig_account2への設定

続いて、上書き用configファイルの設定です。
上書きしないところは~/.gitconfigの設定が引き継がれるので上書きしたところの設定値のみを書けば十分です。
上記に例で乗せているalias等も引き継いでくれます。

```diff:.gitconfig_account2
+[user]
+  name = account2_user
+  email = account2@sample.com
+  signingkey = "~/.ssh/id_ed25519_account2.pub" #設定している場合
+ [gpg "ssh"]
+  allowedSignersFile = /Users/user/.ssh/allowed_signers_account2 #設定している場合
```

### core.sshCommandの設定

最後にcore.sshCommandの設定を行います。
この設定を明示的に行うことでコマンド実行時にどのsshを用いて実行するかが指差せるようになるため、冒頭で紹介したリモートリポジトリのhost名の変更が不要になります。

```diff:.gitconfig
[user]
  name = account1_user
  email = sample@sample.com
  signingkey = "~/.ssh/id_ed25519.pub"
  
+[core]
+ sshCommand = "ssh -i ~/.ssh/id_rsa_account1"
  
[gpg]
  format = ssh
[gpg "ssh"]
  allowedSignersFile = /Users/user/.ssh/allowed_signers
[commit]
  gpgsign = true
[alias]
  st = status
  f = fetch
  rb = rebase
  amd = commit --amend --no-edit
  co = checkout
  cob = checkout -b

[includeIf "gitdir:~/account2/"]
  path = ~/.gitconfig_account2
```

```diff:.gitconfig_account2
[user]
  name = account2_user
  email = account2@sample.com
  signingkey = "~/.ssh/id_ed25519_account2.pub" #設定している場合

+[core]
+ sshCommand = "ssh -i ~/.ssh/id_rsa_account2"

[gpg "ssh"]
  allowedSignersFile = /Users/user/.ssh/allowed_signers_account2 #設定している場合
```

以上の設定を行うことで、
~/account2というディレクトリ配下のgitリポジトリとそれ以外のディレクトリで管理されているgitリポジトリで異なる設定ができるようになったと思います！

さらに、sshCommandを指定したことで、リモートリポジトリをhost名に変更せずに、
`github.com`のままでもgit側がよしなに解釈して実行してくれるようになったと思います！

ちなみにですが、動作確認の際に

```
git config user.name
```

などで確認する際は~/account2で管理されている中のgit initしてあるリポジトリにて実行しないと設定が適用されていないのでご注意ください。
## 最後に

誰かの助けになれていれば幸いです！
もっとよい設定等あればコメントください！