Kanji
・クラウドエンジニア / フリーランス ・1993年生まれ ・愛媛県出身 / 東京都渋谷区在住 ・AWS歴5年 プロフィールの詳細
目次
gh auth switch
gh auth setup-git
~/.gitconfig
includeIf
GH_TOKEN
git push
Permission denied
yq
!gh auth git-credential
僕がこの記事を最初に書いた 2023年2月当時は、GitHub CLI( gh )に複数アカウントを保持・切り替える公式機能が存在しなかったため、 ~/.config/gh/hosts.yml を別名で退避・上書きコピーする自作エイリアスでしのいでいました。
gh
~/.config/gh/hosts.yml
その後、GitHub CLI v2.40.0(2023年12月リリース) で公式のマルチアカウント管理機能 gh auth switch が実装されました。現在(2026年時点、 gh version 2.102.0 で検証)は、設定ファイルを直接書き換えることなく、以下の標準コマンドだけで複数の GitHub アカウント(個人用と会社・案件用など)を即座に切り替えられます。
gh version 2.102.0
# 1. 2つ目以降のアカウントを追加ログイン(既存アカウントは上書きされず追加保持される) gh auth login # 2. 現在のログイン済みアカウント一覧とアクティブ状態を確認 gh auth status # 3. アカウントを切り替える(2アカウントのみなら引数なしで即トグル切り替え) gh auth switch # 4. アカウント名を指定して非対話で一発切り替え(スクリプト・3アカウント以上の場合) gh auth switch -u kanji-shinohara # 5. Git (git push / pull / clone) の HTTPS 認証にも GitHub CLI の切り替えを連動させる gh auth setup-git
単に gh pr create や gh issue list の実行アカウントを切り替えたいだけなら、上記の gh auth switch だけで完結します。
gh pr create
gh issue list
ただ、実際に 1 台の Mac で「会社の業務リポジトリ」と「個人の開発リポジトリ」を毎日行き来していると、 gh auth switch だけでは防げない 3 つの実務上の落とし穴 に何度もハマりました。
Author
user.name
user.email
GITHUB_TOKEN
personal
work
本記事では、公式の gh auth switch の基本操作から、これら 3 つの落とし穴を防ぐ「認証トークンとコミット Author の二層分離設計」、そして僕が手元の環境で今も併用しているロール別エイリアス設定までまとめて解説します。
▲ GitHub CLI (gh auth switch) による API/HTTPS 認証切り替えと Git includeIf による Author 分離の全体像
gh auth login
すでに 1 つ目のアカウント(例:会社用アカウント work-user )でログインしている状態で、そのままもう一度 gh auth login を実行し、2 つ目のアカウント(例:個人用アカウント kanji-shinohara )で認証を通します。
work-user
kanji-shinohara
gh auth login -h github.com -p https -w
現在の GitHub CLI は、デフォルトで認証トークンを OS 標準のセキュアストレージ(macOS の Keychain、Windows の Credential Manager、Linux の Secret Service)に暗号化して保存します。以前のように ~/.config/gh/hosts.yml の中に平文の oauth_token が書き込まれないため、ドットファイルを管理する上でも安全性が大幅に向上しています。
oauth_token
gh auth status
gh auth status を実行すると、現在保持されているすべてのアカウントと、どちらがアクティブ( Active account: true )になっているかが一目で確認できます。
Active account: true
$ gh auth status github.com ✓ Logged in to github.com account kanji-shinohara (keyring) - Active account: true - Git operations protocol: https - Token: gho_************************************ - Token scopes: 'gist', 'read:org', 'repo', 'workflow' ✓ Logged in to github.com account work-taro (keyring) - Active account: false - Git operations protocol: https - Token: gho_************************************ - Token scopes: 'gist', 'read:org', 'repo', 'workflow'
シェルスクリプトや CI チェックなどで「現在アクティブなアカウントだけ」を確認したい場合は、 --active ( -a )フラグ、または JSON 出力オプションが便利です。
--active
-a
# アクティブなアカウントのみを表示 gh auth status --active # 現在アクティブな GitHub ユーザー名だけを文字列として取得(スクリプトでの事前チェック用) gh api user --jq '.login'
アカウントを切り替える際は、以下の 3 通りの呼び出し方を使い分けます。
# パターンA:登録が2アカウントのみの場合(実行するたびに交互にトグル切り替え) gh auth switch # パターンB:ユーザー名を明示して切り替え(3アカウント以上ある場合や自動化スクリプト向け) gh auth switch -u kanji-shinohara # パターンC:GitHub Enterprise Server (GHES) のホストを指定して切り替え gh auth switch --hostname github.company.internal -u work-taro
実行すると、 ✓ Switched active account for github.com to kanji-shinohara と出力され、即座にアクティブアカウントが切り替わります。
✓ Switched active account for github.com to kanji-shinohara
git clone
僕が現場でよく遭遇したのが、「 gh auth switch -u kanji-shinohara で個人アカウントに切り替えたのに、いざ git push origin main を叩くと remote: Permission to kanji-shinohara/repo.git denied to work-taro. (または Repository not found )と怒られる」という現象です。
gh auth switch -u kanji-shinohara
git push origin main
remote: Permission to kanji-shinohara/repo.git denied to work-taro.
Repository not found
原因はシンプルで、Git 本体( git push / git pull )が参照するクレデンシャルヘルパー( osxkeychain や manager )が古いキャッシュを掴んでおり、GitHub CLI 側のアクティブアカウント変更を参照していないためです。
git pull
osxkeychain
manager
まず公式コマンド gh auth setup-git を実行します。
それでも macOS の osxkeychain 等が先に介入して古いアカウントで通信してしまう場合は、 ~/.gitconfig の https://github.com 用ヘルパーを一度空文字 '' でリセットした上で、 !gh auth git-credential のみを使うよう明示的に設定します。
https://github.com
''
# 既存のシステムデフォルトの credential helper を github.com に対して無効化 git config --global --replace-all 'credential.https://github.com.helper' '' # GitHub CLI のアクティブアカウントをそのまま Git 認証に使うよう追加 git config --global --add 'credential.https://github.com.helper' '!gh auth git-credential'
これにより、 ~/.gitconfig には以下の設定が書き込まれ、 gh auth switch で切り替えた瞬間に git push / git pull の HTTPS 認証トークンも 100% 同期して切り替わるようになります。
[credential "https://github.com"] helper = helper = !/opt/homebrew/bin/gh auth git-credential
ここが一番の注意点です。 gh auth switch が切り替えるのは「GitHub API および HTTPS 通信の認証トークン」だけであり、Git コミットに記録される user.name と user.email は一切変更されません。
そのため、認証だけ個人アカウントに切り替えてそのまま git commit すると、個人リポジトリのコミット履歴に会社のメールアドレスが残ってしまう(あるいはその逆)という事故が起きます。
git commit
手動で毎回 git config user.email を打ち直すのは確実に忘れるため、僕は作業ディレクトリ( ~/workspace/personal/ と ~/workspace/work/ )に応じて Git 設定を自動切り替えする includeIf を組み合わせています。
git config user.email
~/workspace/personal/
~/workspace/work/
# ~/.gitconfig(デフォルトは安全のため個人用、または空にしておく) [user] name = Kanji Shinohara email = kanji.shinohara@example.com # 個人開発ディレクトリ配下のリポジトリでは個人用設定を適用 [includeIf "gitdir:~/workspace/personal/"] path = ~/.gitconfig-personal # 業務・クライアント案件ディレクトリ配下のリポジトリでは業務用設定を適用 [includeIf "gitdir:~/workspace/work/"] path = ~/.gitconfig-work [credential "https://github.com"] helper = helper = !/opt/homebrew/bin/gh auth git-credential
# ~/.gitconfig-personal [user] name = Kanji Shinohara email = kanji.shinohara@gmail.com
# ~/.gitconfig-work [user] name = Kanji Shinohara email = kanji.shinohara@company.co.jp
(※ 注意: gitdir:~/workspace/personal/ の末尾のスラッシュ / を忘れるとサブディレクトリに適用されないため、必ず末尾に / を付けてください)
gitdir:~/workspace/personal/
/
これで、「どのフォルダで作業しているか」によってコミットの Author が自動で切り替わり、うっかり社用メールアドレスを個人 OSS リポジトリにコミットしてしまう手戻りをゼロにできます。
gh auth switch を導入した後に「なぜかアカウントが切り替わらない」「 Failed to log in が出る」と詰まったときの判断フローをまとめました。
Failed to log in
MCP サーバーの設定や direnv ( .envrc )などでシェルの環境変数に GH_TOKEN または GITHUB_TOKEN が設定されていると、GitHub CLI は設定ファイル(キーリング)よりも 環境変数を最優先 します。
direnv
.envrc
この状態で gh auth switch を叩くと、以下のようなエラーが出るか、切り替えたつもりでも元のトークンが使われ続けます。
$ gh auth switch X Active account on github.com cannot be switched while GH_TOKEN environment variable is set
gh auth status を叩いて - Token: gho_*** (from GH_TOKEN) と表示されている場合は、 unset GH_TOKEN GITHUB_TOKEN で環境変数を解除してから切り替えてください。
- Token: gho_*** (from GH_TOKEN)
unset GH_TOKEN GITHUB_TOKEN
僕は普段、Claude Code や Antigravity などの AI コーディングエージェントに複数のプロジェクト(個人プロジェクトと業務プロジェクト)を跨いで作業させています。
このとき、AI エージェントがバックグラウンドのサブシェルから git push や gh pr create を実行すると、直前に別タスクで切り替えたアカウントが残っていて Permission denied で止まることがありました。また、プロジェクト共通のルールファイル( .agent/rules/git_workflow.md 等)に生の GitHub ユーザー名( kanji-shinohara 等)をハードコードするよりも、 personal / work という抽象的なロール名(プロファイル名)で呼び出せた方が、ルールやスキルを全リポジトリで共通化できます 。
.agent/rules/git_workflow.md
そこで、以前から使っていた gh switch-profile <プロファイル名> というエイリアスインターフェースを維持したまま、裏側で切り替えを行う設定を引き続き活用しています。
gh switch-profile <プロファイル名>
「具体的な GitHub ユーザー名ではなく gh switch-profile personal や gh switch-profile work のように役割名で切り替えたい」「アカウントごとに hosts.yml ファイル自体を物理分離して管理したい」という場合は、 ~/.config/gh/config.yml の aliases 機能が便利です。
gh switch-profile personal
gh switch-profile work
hosts.yml
~/.config/gh/config.yml
aliases
gh auth switch -u
~/.config/gh/config.yml の aliases に、ロール名から実際の GitHub ユーザー名へのマッピングを 1 行追加するだけです。
# ~/.config/gh/config.yml git_protocol: https aliases: switch-profile: >- !case "$1" in personal) gh auth switch -h github.com -u kanji-shinohara ;; work) gh auth switch -h github.com -u work-taro ;; *) echo "[ERROR] Usage: gh switch-profile <personal|work>" && exit 1 ;; esac && gh auth status --active
これで、人間が手元で叩くときも、AI エージェントがプッシュ前フックで叩くときも、常に以下のコマンドで統一できます。
gh switch-profile personal && git push origin HEAD
hosts.yml.${プロファイル名}
OS キーリングを使わず( gh auth login --insecure-storage )、以前のように ~/.config/gh/hosts.yml.${プロファイル名} として設定ファイルごとバックアップ・切り替えしたい場合は、以下の 4 つのエイリアス( create-profile , switch-profile , delete-profile , list-profiles )を ~/.config/gh/config.yml に登録します。
gh auth login --insecure-storage
~/.config/gh/hosts.yml.${プロファイル名}
create-profile
switch-profile
delete-profile
list-profiles
git_protocol: https aliases: create-profile: '![ -z "$1" ] && echo "[ERROR] Please specify the profile name." && exit 1; gh auth status && read -p "Do you create this profile? (y/N): " yn; case "$yn" in [yY]*) cp ~/.config/gh/hosts.yml ~/.config/gh/hosts.yml.$1 && echo "New hosts file created: ~/.config/gh/hosts.yml.$1";; esac' switch-profile: '![ -z "$1" ] && echo "[ERROR] Please specify the profile name." && exit 1; if [ -e ~/.config/gh/hosts.yml.$1 ]; then cp ~/.config/gh/hosts.yml.$1 ~/.config/gh/hosts.yml && gh auth status && echo "[INFO] Hosts file switched"; else echo "[ERROR] Hosts file not found: ~/.config/gh/hosts.yml.$1"; fi' delete-profile: '![ -z "$1" ] && echo "[ERROR] Please specify the profile name." && exit 1; read -p "Do you delete this profile? (y/N): " yn; case "$yn" in [yY]*) rm -f ~/.config/gh/hosts.yml.$1 && echo "Hosts file deleted: ~/.config/gh/hosts.yml.$1";; esac' list-profiles: '!ls ~/.config/gh/hosts.yml.* | sed -e "s|^.*hosts.yml.||" | sed -e "s|^| - |"'
# プロファイル作成コマンド yq -o yaml -i '.aliases += { "create-profile": "![ -z \"$1\" ] && echo \"[ERROR] Please specify the profile name.\" && exit 1; gh auth status && read -p \"Do you create this profile? (y/N): \" yn; case \"$yn\" in [yY]*) cp ~/.config/gh/hosts.yml ~/.config/gh/hosts.yml.$1 && echo \"New hosts file created: ~/.config/gh/hosts.yml.$1\";; esac" }' ~/.config/gh/config.yml # プロファイル切り替えコマンド yq -o yaml -i '.aliases += { "switch-profile": "![ -z \"$1\" ] && echo \"[ERROR] Please specify the profile name.\" && exit 1; if [ -e ~/.config/gh/hosts.yml.$1 ]; then cp ~/.config/gh/hosts.yml.$1 ~/.config/gh/hosts.yml && gh auth status && echo \"[INFO] Hosts file switched\"; else echo \"[ERROR] Hosts file not found: ~/.config/gh/hosts.yml.$1\"; fi" }' ~/.config/gh/config.yml # プロファイル削除コマンド yq -o yaml -i '.aliases += { "delete-profile": "![ -z \"$1\" ] && echo \"[ERROR] Please specify the profile name.\" && exit 1; read -p \"Do you delete this profile? (y/N): \" yn; case \"$yn\" in [yY]*) rm -f ~/.config/gh/hosts.yml.$1 && echo \"Hosts file deleted: ~/.config/gh/hosts.yml.$1\";; esac" }' ~/.config/gh/config.yml # プロファイルリストコマンド yq -o yaml -i '.aliases += { "list-profiles": "!ls ~/.config/gh/hosts.yml.* | sed -e \"s|^.*hosts.yml.||\" | sed -e \"s|^| - |\"" }' ~/.config/gh/config.yml
各エイリアスの実行コマンドは以下の通りです。
# 現在の認証状態でプロファイルファイルを作成 gh create-profile personal # プロファイル一覧を表示 gh list-profiles # プロファイルを切り替え gh switch-profile personal # 不要になったプロファイルを削除 gh delete-profile personal
最後に、GitHub CLI で複数アカウントを扱うアプローチを比較表に整理します。
--insecure-storage
-u <user>
現在の僕自身の結論としては、認証基盤そのものは公式の gh auth switch (キーリング保管)+ gh auth setup-git に完全移行しつつ、コミット Author の事故防止に ~/.gitconfig の includeIf を張り、さらに AI エージェントからの呼び出し用に gh switch-profile エイリアス を被せる構成が一番ストレスなく回っています。
gh switch-profile
ただ、今後もし GitHub CLI 本体で「リポジトリのディレクトリパスに応じて使用するアカウントを自動選択する機能( gh 版の includeIf のような仕組み)」が公式サポートされれば、プッシュ前の切り替えコマンドすら不要になるはずです。そのあたりの公式アップデートは引き続き追いかけていきたいと思います。
コーディング首位はClaude Opus 5.5(SWE-bench 86.8%・Terminal-Bench 66.4%)とGemini 4 Carbon(Terminal-Bench 65.2%・ ... [続きを読む]
2024年から2026年にかけてのAIコーディングの進化史を総括。GitHub CopilotからClaude Code、Antigravity、Replit、Bolt.newまでの変遷、Webアプリ ... [続きを読む]
AIエージェントの記憶アーキテクチャをLanceDB+SQLiteのハイブリッドGraphRAGへ刷新した話
本記事で解説した 4大AIエージェント(Antigravity, Kiro, Claude Code, Codex)完全対応の AGENTS.md テンプレート、hooks.json、Gitガードスクリプト一式をGumroadにて配布準備中です。
AWS Organizations / Control Tower マルチアカウント設計、IAM Identity Center、Prowler 統制自動化、Terraform / CI/CD 構築を実務アーキテクトが直接支援します。
Google Cloud / Firebase 上で稼働する自社AIプロダクト群。AIクオンツ市場分析「Alpha Radar」およびAI印象診断「CandidLens」を公開中です。