目次
TL;DR
- 仕事用と個人用のGitHubアカウントを使い分けるには、3層の設定が必要
includeIf+insteadOf+gh関数ラッパーを組み合わせることで完全自動化~/work/配下にcdするだけで、すべてが仕事用に切り替わる
2026年1月 更新: 層3の
ghコマンド切り替え方式を改善しました。以前のchpwdフック +gh auth switch方式から、関数ラッパー +GH_TOKEN環境変数方式に変更しています。複数ターミナルウィンドウでの並行作業に対応しました。
背景・課題
解決したかった問題
「仕事用と個人用のGitHubアカウントを使い分けたい」
これは多くの開発者が直面する課題です。手動で切り替えることもできますが、以下の問題がありました。
- 切り替え忘れ: 個人リポジトリに仕事用のメールアドレスでコミットしてしまう
- 操作の煩雑さ:
git configやSSHキーを毎回手動で切り替えるのは面倒 - gh CLIの存在: GitだけでなくGitHub CLI(
gh)も別途切り替えが必要
理想の状態
「ディレクトリを移動するだけで、すべてが自動で切り替わる」
具体的には、~/work/配下に移動したら仕事用、それ以外は個人用として、以下がすべて自動で切り替わる状態を目指しました。
- Gitのコミット情報(
user.name、user.email) - SSHキー(GitHubへの認証)
- GitHub CLI(
ghコマンド)のアカウント
検討した選択肢
選択肢A: 手動で都度設定
各リポジトリで git config user.email を手動設定する方法です。
メリット:
- 追加の設定が不要
デメリット:
- リポジトリを作るたびに設定が必要
- 設定し忘れると間違ったアカウントでコミットしてしまう
- SSHキーやgh CLIは別途管理が必要
選択肢B: direnv + GH_TOKEN
direnvを使って、ディレクトリごとに環境変数を設定する方法です。
# ~/work/.envrc
export GH_TOKEN="ghp_xxxx"
export GIT_AUTHOR_EMAIL="work@example.com"
メリット:
- 環境変数で統一的に管理できる
- direnvは広く使われているツール
デメリット:
- direnvの追加インストールが必要
- トークンをファイルに書く必要がある(セキュリティ懸念)
- プロジェクトごとに
.envrcが必要
選択肢C: includeIf + insteadOf + gh関数ラッパー(採用)
Gitの標準機能とシェル関数を組み合わせる方法です。
メリット:
- 追加ツール不要(Git/Zsh標準機能を使用)
- 設定は一度だけ、以降は自動
- トークンをファイルに書く必要がない
デメリット:
- 設定項目が多い(3層の設定が必要)
- 仕組みの理解が必要
比較表
| 観点 | 手動設定 | direnv | includeIf+α(採用) |
|---|---|---|---|
| 初期設定の手間 | なし | 中 | 大 |
| 日常の手間 | 大 | 小 | なし |
| 追加ツール | 不要 | direnv | 不要 |
| セキュリティ | - | トークンをファイルに保存 | OSキーチェーン |
| 設定忘れのリスク | 高 | 低 | なし |
| 複数ウィンドウでの並行作業 | - | 対応 | 対応 |
最終判断
採用: includeIf + insteadOf + gh関数ラッパー
決め手となった理由:
- 追加ツール不要: GitとZshの標準機能だけで実現できる
- 設定忘れがない: ディレクトリ構造に基づいて自動で判定される
- セキュリティ: gh CLIのトークンはOSのキーチェーンに保存される
- 複数ウィンドウ対応: 環境変数でプロセスごとに認証するため、他のターミナルに影響しない
受け入れたトレードオフ:
- 初期設定は複雑になる(この記事で解説します)
- 仕組みを理解していないとトラブルシューティングが難しい
なぜ「3層」が必要なのか
ここからが本題です。GitとGitHubのアカウント切り替えには、3つの異なる設定が必要です。
┌─────────────────────────────────────────────────────┐
│ あなたのPC │
├─────────────────────────────────────────────────────┤
│ │
│ [層1] Gitのuser設定 │
│ → コミットに記録される名前・メールアドレス │
│ → .gitconfig の includeIf で切り替え │
│ │
│ [層2] SSHキー │
│ → GitHubへpush/pullするときの認証 │
│ → SSH Hostエイリアス + insteadOf で切り替え │
│ │
│ [層3] gh CLIのアカウント │
│ → gh pr create などGitHub操作時のアカウント │
│ → gh関数ラッパー + GH_TOKEN で切り替え │
│ │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────┐
│ GitHub │
│ (個人 or 仕事用) │
└─────────────────────┘
なぜ別々に設定が必要なのか
それぞれが異なるタイミングで使われるからです。
| 層 | いつ使われるか | 何を識別するか |
|---|---|---|
| 層1 | git commit 時 | コミットの作者(Author) |
| 層2 | git push/pull 時 | GitHubへの接続認証 |
| 層3 | gh pr create 等 | GitHub APIの操作者 |
例えば、層1だけ設定しても、push時に間違ったSSHキーが使われてしまいます。3層すべてを正しく設定して初めて、完全な切り替えが実現します。
各層の設定方法
以下、~/work/配下を仕事用、それ以外を個人用として設定する例を示します。
層1: includeIfによるuser設定の自動切り替え
includeIfは、条件に応じて別の設定ファイルを読み込むGitの機能です。
~/.gitconfig(メインの設定ファイル)
# デフォルト(個人用)の設定
[user]
name = Your Personal Name
email = personal@example.com
# ~/work/ 配下では仕事用設定を追加で読み込む
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
~/.gitconfig-work(仕事用の設定ファイル)
[user]
name = Your Work Name
email = work@company.com
解説
[includeIf "gitdir:~/work/"]: 現在のリポジトリが~/work/配下にある場合に適用path = ~/.gitconfig-work: この設定ファイルを読み込む
重要なポイント:
gitdir:の後のパスは末尾に/を付ける(~/work/であって~/workではない)- 末尾の
/は**(任意のサブディレクトリ)として解釈される - 後から読み込まれた設定が優先される(だから仕事用の
user.nameで上書きされる)
動作確認
# 個人用ディレクトリで確認
cd ~/personal/some-repo
git config user.email
# → personal@example.com
# 仕事用ディレクトリで確認
cd ~/work/some-project
git config user.email
# → work@company.com
設定が正しく読み込まれているかは、以下のコマンドで詳しく確認できます。
git config --list --show-origin
これにより、各設定がどのファイルから来ているかが表示されます。
層2: SSH Hostエイリアス + insteadOfによるSSHキー切り替え
SSHキーの切り替えは2つの設定を組み合わせます。
ステップ1: SSH設定ファイルでHostエイリアスを定義
~/.ssh/config に以下を追加します。
# 個人用(デフォルト)
Host github.com
IdentityFile ~/.ssh/id_ed25519_personal
# 仕事用(エイリアス)
Host github-work
HostName github.com
IdentityFile ~/.ssh/id_ed25519_work
解説
Host github.com:github.comに接続するときの設定Host github-work:github-workという架空のホスト名を定義- 実際の接続先は
HostName github.com(本物のGitHub) - でも使うSSHキーは
id_ed25519_work(仕事用)
- 実際の接続先は
これにより、git@github-work:org/repo.gitにアクセスすると、仕事用のSSHキーが使われます。
ステップ2: GitのinsteadOfでURLを自動変換
仕事用リポジトリでは、github.comへのアクセスを自動的にgithub-workに書き換えます。
~/.gitconfig-work に以下を追加します。
[user]
name = Your Work Name
email = work@company.com
# SSH形式のURLを変換
[url "git@github-work:"]
insteadOf = git@github.com:
# HTTPS形式のURLも変換
[url "git@github-work:"]
insteadOf = https://github.com/
解説
insteadOf: GitがURLを解決するとき、自動的に置換する- 例えば
git clone git@github.com:org/repo.gitを実行すると- 内部的には
git@github-work:org/repo.gitに変換される - SSH設定により
github-workは仕事用SSHキーで接続される
- 内部的には
動作確認
# 仕事用リポジトリでリモートURLを確認
cd ~/work/some-project
git remote -v
# → origin git@github.com:company/repo.git (fetch)
# ↑ 表示はgithub.comのまま
# 実際に使われるURLを確認
git config --get-regexp 'url.*'
# → url.git@github-work:.insteadof git@github.com:
層3: gh関数ラッパーによるgh CLIアカウント切り替え
GitHub CLI(gh)は、v2.40.0から複数アカウントのサポートが追加されました。
事前準備: 両方のアカウントでログイン
# 1つ目のアカウントでログイン
gh auth login
# 2つ目のアカウントでログイン(追加される)
gh auth login
# ログイン状況を確認
gh auth status
gh auth statusを実行すると、ログイン済みの全アカウントと、現在アクティブなアカウントが表示されます。
~/.zshrcへの設定追加
########################################
# GitHub CLI アカウント切り替え(関数ラッパー方式)
# ~/work 配下では仕事用、それ以外は個人用
# アカウント名は ~/.zshrc.local で設定:
# GH_PERSONAL_ACCOUNT="your-personal"
# GH_WORK_ACCOUNT="your-work"
########################################
gh() {
local token
if [[ "$PWD" == "$HOME/work"* ]]; then
token=$(command gh auth token --user "$GH_WORK_ACCOUNT" 2>/dev/null)
else
token=$(command gh auth token --user "$GH_PERSONAL_ACCOUNT" 2>/dev/null)
fi
if [[ -n "$token" ]]; then
GH_TOKEN="$token" command gh "$@"
else
command gh "$@"
fi
}
~/.zshrc.local でアカウント名を設定
# GitHubのユーザー名を設定
GH_PERSONAL_ACCOUNT="your-personal-username"
GH_WORK_ACCOUNT="your-work-username"
解説
関数ラッパー方式とは:
シェル関数でghコマンドをラップし、実行時にディレクトリをチェックして適切なトークンを使用します。
| 要素 | 説明 |
|---|---|
gh auth token --user | 指定アカウントのトークンを取得 |
GH_TOKEN="..." command gh | 環境変数をそのコマンドにのみ渡す(プロセスローカル) |
command gh | 関数ではなく実際のghコマンドを呼ぶ |
commandキーワードのポイント:
command gh "$@"
シェル関数内でghを呼ぶと再帰的に自分自身が呼ばれてしまいます。commandキーワードを使うことで、関数ではなく実際のコマンドを呼び出します。
なぜこの方式を採用したか:
以前はchpwdフック + gh auth switch方式を使用していましたが、複数のターミナルウィンドウで並行作業する際に問題がありました。
- 旧方式:
gh auth switchはグローバル設定を変更するため、片方のウィンドウでの切り替えがもう片方にも影響する - 新方式:
GH_TOKEN環境変数はそのコマンドの実行時のみ有効(プロセスローカル)なので、他のウィンドウに影響しない
なぜ~/.zshrc.localにアカウント名を書くのか:
- アカウント名は個人情報なので、dotfilesリポジトリには含めたくない
~/.zshrc.localはGit管理外のファイルとして運用する
動作確認
# 仕事用ディレクトリで確認
cd ~/work/some-project
gh api user --jq '.login'
# → work-username
# 個人用ディレクトリで確認
cd ~/personal/my-repo
gh api user --jq '.login'
# → personal-username
注意: gh auth statusはグローバル設定を表示するため、関数ラッパー方式では現在の状態を正確に反映しません。実際に使用されるアカウントを確認するには、上記のようにgh api userを使用してください。
全体の動作確認
設定が完了したら、以下の手順で確認します。
# 1. 個人用ディレクトリで確認
cd ~/personal/my-repo
git config user.email # → personal@example.com
gh api user --jq '.login' # → personal-username
# 2. 仕事用ディレクトリで確認
cd ~/work/company-project
git config user.email # → work@company.com
gh api user --jq '.login' # → work-username
# 3. 実際にpushできるか確認(仕事用リポジトリで)
git push --dry-run # 仕事用SSHキーで認証される
採用後の結果
うまくいったこと
- 切り替え忘れがゼロに: ディレクトリ構造で自動判定されるので、意識する必要がない
- 作業開始の手間が消えた: 以前は毎回「どのアカウントだっけ」と確認していた
- トラブルが減った: 間違ったアカウントでコミット/プッシュする事故がなくなった
- 複数ウィンドウでの並行作業が可能に: 関数ラッパー方式により、仕事用と個人用のターミナルを同時に開いて作業できるようになった
改善の経緯
当初はchpwdフック + gh auth switch方式を採用していましたが、複数のターミナルウィンドウで並行作業する際に問題が発生しました。gh auth switchはグローバル設定を変更するため、片方のウィンドウでの切り替えがもう片方にも影響してしまいます。
そこで関数ラッパー + GH_TOKEN環境変数方式に変更しました。この方式では:
- 環境変数はコマンド実行時のみ有効(プロセスローカル)
cd時のフックが不要でシンプル- グローバル設定(
gh auth status)を変更しない
学んだこと
1. GitとGitHubの認証は別物
「Git設定を変えればOK」と思いがちですが、実際にはSSH認証、GitHub API認証など複数のレイヤーがあります。それぞれを理解して設定する必要があります。
2. 標準機能の組み合わせで実現できる
includeIf、insteadOf、シェル関数はすべて標準機能です。新しいツールを追加しなくても、既存の仕組みの組み合わせで目的を達成できました。
3. UXを追求する価値
「cdするだけ」という体験にこだわりました。設定は複雑ですが、日常の操作はシンプルになります。初期投資と日常のコストのバランスを考えて判断することが重要です。
参考
公式ドキュメント
- gh auth token - GitHub CLI Manual
- Using the GitHub CLI across GitHub platforms - GitHub Docs
- git-config - includeIf - Git Documentation
関連記事
- Log in to multiple GitHub accounts with the CLI - GitHub Changelog
- Git config with multiple identities - GitHub Gist