はじめに
諸事情あり、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に登録します。
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」とかでググることになりました..
[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等も引き継いでくれます。
+[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名の変更が不要になります。
[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
[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してあるリポジトリにて実行しないと設定が適用されていないのでご注意ください。
最後に
誰かの助けになれていれば幸いです!
もっとよい設定等あればコメントください!