副業や個人開発を始めると、GitHub アカウントが複数になることがあります。副業用 Mac と個人用 Mac をきれいに分けられれば楽ですが、現実には 1 台の Mac で 副業用の GitHub アカウント個人用の GitHub アカウント を両方使う場面が出てきます。

自分もそのパターンで、最初は gh auth switch でなんとかしていました。ただある日、個人 repo に副業用のメールアドレスで commit しそうになりました。push する前に気づけたので助かりましたが、ここで一回手が止まりました。これは毎回気合いで見るより、仕組みで防ぐのが良さそうだと思いました。

ここでは、そのとき最終的に落ち着いた ~/.ssh/config + ~/.gitconfigincludeIf 設定をメモとして残します。同じように 1 台の Mac で複数アカウントを扱っている人向けの TIPS です。設定しておくと、あとからじわっと効きます。

まずは gh auth switch で何とかしようとした

GitHub CLI の操作は切り替わる

GitHub CLI(gh)には、アカウント切り替えコマンド gh auth switch があります。複数アカウントを 1 台の Mac で扱うとき、最初に思いつくのはこれだと思います。自分もそうでした。

# 登録されているアカウント一覧と現在のアクティブを確認
gh auth status

# 別のアカウントに切り替える
gh auth switch

gh auth login であらかじめ登録しておいた複数アカウントの中から、どれをアクティブにするかを選ぶだけで、gh repo clonegh pr create といった CLI 操作はそのアカウントに切り替わります。GitHub CLI だけを見ている範囲では、これで足りているように見えます。自分も最初は「これで解決では?」と思っていました。

commit Author は残る

ただ、実はこれだけでは commit に刻まれる Author 情報 までは切り替わりません。次の節がその話です。

でも、Author は別レイヤーだった

きっかけは commit 前の違和感

きっかけは、個人 repo を clone して作業していたときのことです。何気なく commit しようとして、念のため Author を見たら「あれ?」となりました。

gh の認証が副業アカウントに向いている状態で、ターミナルだけ別に開いて個人 repo に commit しようとしました。gh auth switch を打って個人アカウントに切り替えたつもりだったのですが、git log を確認すると Author が副業のメールアドレスのままでした。

理屈としては当然で、gh auth switch が切り替えるのは GitHub CLI の認証コンテキストだけです。git commit の Author に入る user.name / user.email は、~/.gitconfig か repo ローカルの .git/config から読まれます。GitHub への push 認証と、commit に刻まれる Author は別レイヤーです。

鍵・CLI 認証・Author を分けて見る

このとき、自分の Mac はおおむねこういう状態でした。今見ると、混ざってもおかしくない構成です。

  • グローバル ~/.gitconfig には副業用の user.email がベタ書きされていた
  • gh には副業アカウントと個人アカウントの両方が登録されていた
  • SSH 鍵は両方とも ~/.ssh/ にある

つまり「鍵」「CLI 認証」「Author」が三つとも別々に動いていて、どれかを切り替え忘れた瞬間に混ざる構成でした。gh auth switch を毎回手動でやっている時点で、少し不安が残りますよね。人間の記憶に寄せすぎると、いつか漏れます。

commit〜push に関わる 3 レイヤー SSH 鍵 / CLI 認証 / Author 情報 の3レイヤーが別々に管理されていて、どれかを切り替え忘れるとアカウント情報が混ざる構造 commit〜push に関わる 3 レイヤー SSH 鍵 ~/.ssh/ 配下 どの鍵でつなぐか push 認証に効く CLI 認証 gh auth switch で切替 どのアカウントとして CLI 操作するか gh / PR 作成に効く Author 情報 ~/.gitconfig の user.* commit に刻まれる 名前 / メール commit 履歴に残る 3 つが別々に動くので、どれか切り替え忘れると混ざる 特に Author 情報は gh auth switch だけでは切り替わらない
commit〜push に関わる 3 レイヤー。`gh auth switch` だけでは Author 情報まで揃わない。

ここから、作業するディレクトリを分けたら、鍵と Author も自然に揃ってほしい、という方向に組み直していきます。つまり「ディレクトリを見れば設定も決まる」形です。

push 認証は SSH の Host alias で分ける

Host alias で鍵を固定する

最初に手を入れたのは ~/.ssh/config です。まずは push 認証に使う鍵を、アカウントごとに分けます。

GitHub 自体はホスト名としては github.com 一つしかないので、SSH レベルで分けるには Host alias を使います。~/.ssh/config に「個人アカウント用の架空のホスト名」を作り、そこに専用の鍵を紐づけます。

# ~/.ssh/config

# 副業アカウント(仮: github-side)
Host github-side
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_side
  IdentitiesOnly yes

# 個人アカウント
Host github-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_personal
  IdentitiesOnly yes

IdentitiesOnly yes を入れているのは、ssh-agent に他の鍵が乗っていても、この Host では指定した鍵しか使わせないためです。これがないと、agent に登録した順で別の鍵が先に試され、Too many authentication failures で弾かれることがあります。ここは入れておくと安心です。

clone と接続確認

clone するときは alias 名を使います。

# 個人 repo
git clone git@github-personal:your-handle/your-repo.git

接続テストは ssh -T で確認できます。

ssh -T git@github-personal
# => Hi your-handle! You've successfully authenticated, ...
~/.ssh/config の Host alias で接続を分ける github-side と github-personal の2つの架空ホスト名を、同じ github.com に向けつつ別の鍵を紐づける構造 Host github-side IdentityFile id_ed25519_side 副業用の鍵だけ使う Host github-personal IdentityFile id_ed25519_personal 個人用の鍵だけ使う github.com 同じホスト名でも どの鍵で来たかで判別 紐づく アカウント で認証される git@github-side:... と git@github-personal:... で接続経路を明確に分離
同じ github.com に対して、Host alias で別の鍵を使い分ける構造。

これで「鍵」のレイヤーは分かれました。次は、commit に残る Author の自動切替です。ここをやらないと、まだ履歴に残る名前とメールが混ざります。

commit Author は includeIf で場所に紐づける

gitdir で設定ファイルを追加する

Git には、~/.gitconfig の中から 作業ディレクトリのパスに応じて別の設定ファイルを読み込む includeIf という仕組みがあります。これを使うと、特定のディレクトリ配下では user.nameuser.email を別の値に上書きできます。今回ほしかったのは、まさにこの「場所で決まる」仕組みでした。

自分は、個人プロジェクトを ~/workspace/personal/ 配下にまとめているので、「personal/ 配下では個人アカウントの Author を使う」というルールを書きました。

# ~/.gitconfig

[user]
    name  = <副業用の表示名>
    email = <副業用のメールアドレス>

# personal/ 配下のときだけ個人用の設定を追加で読む
[includeIf "gitdir:~/workspace/personal/"]
    path = ~/.gitconfig.personal

include される側はこんな感じです。

# ~/.gitconfig.personal

[user]
    name  = <個人用の表示名>
    email = <個人用のメールアドレス>

gitdir: のパスは末尾のスラッシュ重要で、~/workspace/personal/ と書くとその配下全部にマッチします。後から読まれる側が勝つので、personal/ 配下では個人用の user.email で上書きされます。

効いているかを確認する

設定が効いているかは、それぞれのディレクトリで git config --get を打てば確認できます。

# 副業用ディレクトリで
cd ~/workspace/side-project
git config --get user.email
# => <副業用のメール>

# 個人用ディレクトリで
cd ~/workspace/personal/your-repo
git config --get user.email
# => <個人用のメール>

ここまで揃えれば、SSH 接続は ~/.ssh/config の Host alias で、Author は ~/.gitconfigincludeIf で、それぞれ自動で切り替わります。gh auth switch を毎回叩かなくても、personal/cd した時点で commit の Author は個人用になります。この「cd した時点で決まる」のがかなり楽です。

まとめ:Author は場所で決まるようにする

見るべきレイヤー

includeIf は、一度入れたら普段は意識しなくてよい類の設定です。最初だけ少し手間はありますが、設定後は「副業用ディレクトリで commit したら副業用の Author」「個人用ディレクトリで commit したら個人用の Author」が自然に動きます。こういう設定は、忘れた頃に助けてくれます。

ポイントを並べておきます。

  • gh auth switch は GitHub CLI の認証だけ。Author までは切り替わらない
  • SSH レベルでは ~/.ssh/config の Host alias と IdentitiesOnly yes で鍵を分ける
  • Author レベルでは ~/.gitconfigincludeIf でディレクトリごとに上書きする
  • 効いているかは git config --get user.email で都度確認できる

副業や個人開発で 1 Mac 2 アカウント運用に踏み込むなら、早めに入れておくと安心できる設定です。念のため git config --get user.email を見る癖だけ残しておくと、さらに落ち着いて作業できます。