はじめに #
先日 open sourceにpull requestを出した時に、仕事用のアカウントから抜け出せなくてすごく困った。普段はなんとなくやり過ごしていたんだけど今回はとてもハマった。心が擦り切れてしまったので時間がある時に整理しておこうと思います。環境はmacです。
最初にポイントを整理します #
この記事で学べること #
- GitHubのマルチアカウント運用におけるHTTPS方式の具体的な設定手順
- macOSのキーチェーンとgit credential.helperの連携
- VSCodeのaskpassによる自動認証の挙動とその制御方法
- アカウント切り替え時のトラブルシュート実例と解決策
- gitconfigのincludeIfによるuser.xxxの自動切り替え
この運用のメリット #
- リポジトリごとに明示的にアカウントを分離できる
→ 誤ったアカウントでpushしてしまう事故を防止 - macOSのキーチェーンを活用することで認証情報の管理が容易
→ セキュリティと利便性の両立 - 公式ドキュメントに沿った標準的な方法
→ 将来的な運用変更やトラブル時の情報収集がしやすい
この運用のデメリット・注意点 #
- PAT(Personal Access Token)の管理が煩雑になりやすい
→ リポジトリごとにPATの入力が必要 - credential.helperの多重設定やVSCodeのaskpassなど、環境依存の罠が多い
→ トラブル時はキャッシュやUIの確認が必須
こんな人におすすめ #
- 仕事用・個人用など複数のGitHubアカウントを使い分けたい人
- 会社PCや個人PCで安全にアカウントを切り替えたい人
- SSHキー管理が面倒・HTTPSで統一したい人
今回やってみた方法 #
SSHを使わずにHTTPSを使った方法を採用しました。 SSHの場合は SSHの場合 を参考にすると良さそうです。 以下の手順です。
- 資格情報マネージャを確認する。
git config --get-all credential.helper
- 資格情報を削除する。keychainのuiから削除
- 完全なリモート URL の資格情報をキャッシュするように Git を構成する。
git config --global credential.https://github.com.useHttpPath true
- askpassを無効にしてデフォルトアカウントでの自動ログイン施行を無効にする。VSCodeのユーザ設定に
"git.terminalAuthentication": false
を追加 - git config ユーザ名、アカウントの自動設定をする
以上でリポジトリ事のアカウント情報がkeychainで管理できます。 keychainを明示的に使ってアカウント情報を管理する感じで、レポジトリ毎にPATをいれる必要があります。 HTTPS方式はリポジトリごとに認証情報を分離しやすいが、PATの管理が煩雑になる。一方SSHは一度キーの設定をしてしまえばその後困ることは少なそうです。 今の自分はPATの存在を意識しつつ開発したいので、しばらくはこれでやってみます。
今までどうやっていたか #
記憶が曖昧ではあるのだけれど、アカウントを間違った時は git config user.name "hoge" && git config user.email "fuga@hogo.com
みたいにやっていたと思う。
本記事を書いて思い返してみるとSSHの設定がされていたのかもしれない。今までこれでアカウントの切り替えをできていたともうのだけれども今回はそれではだめだった。
よくあるハマりどころ #
今回動作確認でハマったところを先に記載しておきます
- credential.helperが複数設定されていると、どちらか一方のキャッシュが残り続ける
- VSCodeのaskpassが有効だと、意図しないアカウントで自動認証される
- osxkeychainのキャッシュ削除はUIからの操作が確実
公式の解説を読んで手順を整理する #
「1台のパソコンで複数のアカウントのプロジェクトにコントリビュートしたかったら、Git configurationを変更すればいいよ!」ということなので、この記事は重要そう。
HTTPS と SSH を使用する 2 つのアカウントへのコントリビューション #
1 つのワークステーションから 2 つのアカウントでコントリビュートする場合は、アカウントごとに異なるプロトコルと資格情報を使用してリポジトリにアクセスできます。
つまり、例えばアカウントA,Bがあるとき、アカウントAはHTTPSで、アカウントBはSSHでアクセスすればアクセス仕分けできるよ。ってことか? 前者はcredential managerなどに頼り、後者はssh keyを管理する感じですね。確かに2アカウントならそれで良さそう。だけど、cloneするときのURL忘れてまた引っかかっちゃいそうな気もする。
HTTPS と personal access token を使って複数のアカウントにコントリビュートする #
または、両方のアカウントに HTTPS プロトコルを使う場合は、リポジトリごとに異なる資格情報を格納するように Git を構成することで、アカウントごとに異なる personal access token を使用できます。
やりたいことはこれな気がする。
-
ターミナルを開く
-
資格情報マネージャーを使用していることを確認するには、次のコマンドを入力します。
git config --get credential.helper
-
出力で資格情報マネージャーを使用していることが確認された場合は、資格情報マネージャーの保存された資格情報をクリアします。
- 出力に資格情報マネージャーの名前が含まれていない場合は、資格情報マネージャーが構成されていないため、次の手順に進むことができます。
- 出力が osxkeychain の場合、macOS キーチェーンを使用しています。 認証情報を消去するには、コマンド ラインで認証情報ヘルパーを使用します。
$ git credential-osxkeychain erase host=github.com protocol=https > [Press Return] >
- 出力が manager (前のバージョンでは manager-core) の場合は、Git Credential Manager を使用しています。 資格情報をクリアするには、次のコマンドを実行します。
echo "protocol=https\nhost=github.com" | git credential-manager erase
:::message 自分の場合、
git config --get credential.helper
の出力がcache
でした。git credential-cache exit
でキャッシュをクリアできるはず、、、ですが実行後もgit push
できてしまいました。macのキーチェーンアクセス(osxkeychain)
も設定されていて、こちらを見に行ってしまっているようです。–get-allを使うと両方設定されていることがわかりました。
git config --get-all credential.helper osxkeychain cache
試しにoexkeychainのキャッシュを削除する上述のコマンドを実行してみましたが、これまた消えない。むむむ・・・git credentialで消せるのはgit credentialで登録した情報だけらしい。以前手動で登録した認証情報が残ってしまっているっぽいので、いったんUIから全削除する。
$ git remote set-url origin https://github.com/xxxxxxxx/xxxxxxxx.git
。これでアクセスできなくなった! つまり以前実施したssh keyの設定が残っているということですね。 ::: -
GitHub でアクセスする各リポジトリの完全なリモート URL の資格情報をキャッシュするように Git を構成するには、次のコマンドを入力します。
git config --global credential.https://github.com.useHttpPath true
以上の設定で、今後cloneした時にアカウントが聞かれてそのアカウントをキーチェーンが覚えてくれればいい感じか。:::message git fetchすると以下のエラーが出て、アカウントを聞いてくれない。 (あるいはアカウント名とパスワードを聞かれることなくすんなり
git fetch
できてしまう)$ git fetch remote: Repository not found. fatal: repository 'https://github.com/kiitosu/zenn-contents.git/' not found
トレース情報を出してみる
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git fetch
09:53:00.689111 run-command.c:661 trace: run_command: ‘/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass.sh’ ‘Username for ‘'‘https://github.com’'’: ' 09:53:00.802830 run-command.c:661 trace: run_command: ‘/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass.sh’ ‘Password for ‘'‘https://112617635@github.com’'’: '
ここからわかるのは「112617635」というアカウントを使ってログインをここ見ていること。
askpass.sh
というコマンドを使ってパスワードを解決しようとしていること。だとすると、「11267635」のアカウントが「kiitosu」のアカウントにアクセスできないためにエラーになっている。askpassはVSCode
が使っているらしい。なのでVSCodeのUserのsettings.json
に以下を追加してASKPASSを無効化すると、勝手にデフォルトアカウントでログインを試みてエラーになることはなくなる。“git.terminalAuthentication”: false
あるいは以下のようにコマンドで指定しても良い。
GIT_ASKPASS= git fetch
:::
-
アカウントごとに repo スコープを持つ専用の personal access token (classic) を作成します。 または、アカウントごと、自分がメンバーになっている organization ごとに、目的のリポジトリへのアクセスが可能で、リポジトリの内容に対する読み取りと書き込みのアクセス許可を持っている fine-grained personal access token を作成します。 詳しくは、「個人用アクセス トークンを管理する」をご覧ください。
-
Git を使用してリポジトリをクローンしたり、既にクローンしたリポジトリ内のデータにアクセスしたりすると、Git によって資格情報が要求されます。 リポジトリに対してアクセス権を持つアカウントの personal access token を指定してください。Git を使い、リポジトリのフル リモート URL に基づいてpersonal access tokenをキャッシュします。こうすることで、正しいアカウントを使って、リポジトリ データにアクセスして GitHub.com に書き込むことができるようになります。
以上でレポジトリ毎にアカウント、PATを設定し保存することができるようになりました。 レポジトリで間違ったアカウントで作業してしまうことはなくなりますね。認証の流れは以下のようなイメージですね。
flowchart TD
A[URL認証<br>(例:https://user:token@github.com/owner/repo.git)]
B[osxkeychain<br>(macのキーチェーンに保存された認証情報)]
C[cache<br>(一時的なgit認証キャッシュ)]
D[askpass自動<br>(VSCode等でデフォルトアカウント自動認証)]
E[手動入力<br>(ユーザーが直接入力)]
Z[認証成功]
A --> Z
A --> B
B --> Z
B --> C
C --> Z
C --> D
D --> Z
D --> E
E --> Z
SSH と GIT_SSH_COMMAND を使用する複数のアカウントへのコントリビューション #
こっちの読み込みは割愛!SSHを使う場合はこちらの記事が参考になりそうです。
SSHを使う場合 #
git config ユーザ名、アカウントの自動設定 #
以上で、アカウントを間違えずにレポジトリ毎に適切なアカウントでアクセスできるようになりました。しかし、git config user.name
git config user.emain
はアカウント情報ではなく単なる名前とメールアドレスの情報です。git config user.name "hoge" && git congig user.email "fuga@hogo.com
と全てのレポジトリで実施するのは面倒です。これも楽をしたいところです。
特定のuser.name, user.emailを使いたいディレクトリに以下の .gitconfig
ファイルを配置します。
# globalな.gitconfigから呼び出され、本ファイル以下のuser.name, user.emailを設定します
[user]
email = fuga@hogo.com
name = hoge
globalなconfigのファイルに以下を設定します
[includeIf "gitdir:/Users/xxxxxxxx/the_place/"]
path = /Users/xxxxxxxx/the_place/.gitconfig
以上で、 /Users/xxxxxxxx/the_place/
以下のディレクトリには指定した user.name
, user.email
が使われます。
まとめ #
今回まとめた方法はmacのkey chainにおまかせできる、レポジトリ毎にアカウントを明示的に指定できる、というのが良い方法だったかなと思います。 keychainにおまかせするため設定が比較的少なくて済むのも良い点かなと思います。 しばらくこれで進めてみたいと覆います。
その他情報 #
今回の話とはちょっと違うマルチアカウントサポート関連
GitHub.comでマルチアカウントサポートを開始したという記事。 これはGitHubのwebページでアカウントが切り替えられるようになった、今回の趣旨とは関係ない。
この記事もGithubのwebページでアカウントをスイッチする方法の説明。今回の趣旨とは関係ない
Reply by Email