はじめに
複数のGitHubアカウントを使い分けていると、git push したときにこんなエラーに遭遇することがあります。
remote: Permission to user-a/my-repo.git denied to user-b.
fatal: unable to access 'https://github.com/user-a/my-repo.git/': The requested URL returned error: 403
これは「user-a のリポジトリに push しようとしたのに、ローカルに保存されている認証情報が別アカウント(user-b)のものだった」ために起きる 403 エラーです。
この記事では、古い認証情報を消して入れ直す方法だけでなく、リポジトリごとに使うアカウントを固定して自動で切り替える方法までまとめます。「あとで別アカウントに戻したい」というときに毎回消す必要がなくなります。
対象環境
- OS: Windows
- 認証ヘルパー: Git Credential Manager(GCM)
- 接続方式: HTTPS
自分の環境の認証ヘルパーは次のコマンドで確認できます。
git config --get credential.helper
出力が manager(または manager-core)ならこの記事の手順が使えます。
なぜ403になるのか
HTTPS経由でGitHubに接続すると、GCMがWindowsの「資格情報マネージャー」に認証情報を保存します。一度あるアカウントでサインインすると、その情報が使い回されます。
そのため、別アカウントのリポジトリに push しようとしても保存済みの認証情報がそのまま使われ、権限がないアカウントとして扱われて 403 になります。
まずは急ぎで直す:古い認証情報を削除する
取り違えている認証情報を一度削除します。Git Bash で以下を実行します。
printf "protocol=https\nhost=github.com\n" | git credential-manager erase
GUIから消したい場合は、以下の手順でも削除できます。
- 「コントロールパネル」→「資格情報マネージャー」を開く
- 「Windows 資格情報」を選ぶ
-
git:https://github.comを探して「削除」
削除後にもう一度 push すると、サインインを求められます。ここで目的のアカウント(この記事の例では user-a)でサインインしてください。
git push
ブラウザで別アカウント(例では user-b)にログインしたままだと、認証時にそちらが選ばれてしまいがちです。取り違えが起きる場合は、一度ブラウザ側でGitHubからログアウトしてから push すると確実です。
本題:リポジトリごとにアカウントを固定する
毎回削除して入れ直すのは面倒です。GCMにはURLごとに使うユーザー名を指定する仕組みがあるので、これを使ってリポジトリごとにアカウントを固定します。
user-a を使うリポジトリで、そのフォルダに移動して次を実行します。
git config credential.https://github.com.username user-a
user-b を使う別のリポジトリでは、そのフォルダで次を実行します。
git config credential.https://github.com.username user-b
こうしておくと、GCMは user-a 用と user-b 用の認証情報を別々に保存し、各リポジトリの設定に従って自動で正しいアカウントを選んでくれます。「戻す」ために毎回認証情報を消す必要はなくなります。
初回のセットアップ手順(まとめ)
- 取り違えている認証情報を一度削除する
printf "protocol=https\nhost=github.com\n" | git credential-manager erase
- このリポジトリで使うアカウントを固定する
git config credential.https://github.com.username user-a
- push してサインインする
git push
これ以降、両アカウントの認証情報がGCMに保存され、リポジトリの設定に従って自動的に使い分けられます。
コミットの著者情報も切り替える
上記の設定は**認証(push できるか)**の話です。コミットに記録される著者名・メールアドレス(user.name / user.email)は別物なので、こちらもリポジトリごとに合わせておくと安全です。
git config user.name "user-a"
git config user.email "user-aのメールアドレス"
--global を付けずにリポジトリ内で設定すれば、そのリポジトリだけに適用されます。認証はあくまでトークン/サインインで決まり、user.name / user.email はコミットの表示名として使われる、という点を押さえておきましょう。
補足:HTTPS認証にはトークンが必要
GitHubのHTTPS認証では、パスワードではなく Personal Access Token(PAT) が必要です。サインイン画面のパスワード欄には、GitHubの Settings → Developer settings → Personal access tokens で発行したトークンを入力します。GCM経由でブラウザ認証する場合は自動で処理されることが多いですが、うまくいかないときはトークンを直接入力する方法を覚えておくと安心です。
代替案:SSH接続に切り替える
トークン管理が面倒なら、SSH接続に切り替える選択肢もあります。
git remote set-url origin git@github.com:user-a/my-repo.git
ただしSSHはSSHで、アカウントごとに鍵を用意して ~/.ssh/config でホストを出し分ける設定が必要になります。今回のようにHTTPSのまま使い続けたい場合は、本記事の「リポジトリごとにアカウントを固定する」方法が手軽です。
まとめ
-
403 denied to <別アカウント>は、ローカルの認証情報が別アカウントのままなのが原因 - 急ぎなら
git credential-manager eraseで削除して入れ直す - 恒久的な対策として
git config credential.https://github.com.username <アカウント名>でリポジトリごとに固定すると、自動で切り替わり毎回消す必要がなくなる - 認証(push権限)とコミットの著者情報(
user.name/user.email)は別物なので、必要なら両方設定する
複数アカウントを使い分ける人は、リポジトリごとの credential.https://github.com.username 設定を最初にやっておくのがおすすめです。