Edited at

https時代のgitアカウントを使い分ける方法


時代はhttps


https://help.github.com/articles/set-up-git/



  • GitHubではhttps推奨になっているし…

  • httpsのほうがclone速度はやいし…

  • まとめに書くけどhttpsにすると覚えることが1個だけでラク

[2018-10-29: 追記]

ミスリード誘いそうなので当エントリおよび筆者のスタンスを書いておきます。


  • 個人的にはhttpsのほうが速度がはやいし管理手法も覚えやすいと思っている


    • 特別SSHである必要がないのならhttpsでやりたい

    • SSHでなければならない、あるいは明らかなメリットがある場合はSSH接続する



  • どちらも一長一短


    • 適材適所・十人十色で選択するべき



  • SSHをやめてhttpsを使いましょうという扇動エントリではない


SSHでアカウントを使い分けるときはどうしていたか

~/.ssh/configを作成して

host github.com-main

HostName github.com
IdentityFile ~/.ssh/id_rsa_github
User git

host github.com-sub
HostName github.com
IdentityFile ~/.ssh/id_rsa_github_sub
User git

みたいなことを書いてssh-add -K ~/.ssh/id_rsa_githubして

$ git clone git@github.com-main:username/repo.git

この形式でcloneしたりしていた。

git@github.com-mainとかgit@github.com-subとか長いし憶えられないしでつらい。アカウントの数が増えるたびにconfigに足す設計になるのもつらい気がする。

あるいは

$ GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example -F /dev/null" git clone example

Git環境変数にGIT_SSH_COMMANDが生えてからこうもできていたけどコマンド長いし憶えられないし毎回鍵のパスいるしでつらい気がする。

git2.1.0以降は.gitconfigで管理できるようになって

$ git config core.sshCommand "ssh -i ~/.ssh/id_rsa_example -F /dev/null"

で鍵指定したりできるようになって便利、だけどそもそもローカルの.gitconfigが必要になってきてちょっぴりつらい。


https://superuser.com/questions/232373/how-to-tell-git-which-private-key-to-use


まあSSHでのアカウント切り替えはstackexchangeのこのスレッドが一番まとまっていると思っている



本題前のCaveat


  • 個人的なメモで書いているので多分に間違ってたりするかもしれない


  • ssh-keygenしてからのはなしなのでキージェネレーションのやりかたは書かない


  • ひとつのマシンでgitアカウントを使い分けたい


  • 筆者はMacOS環境なのでMacOS前提で書かれています



そもそもコミッター情報(コミッター名とメアド)はどこに依存しているか

gitのコミッター名とメアドは.gitconfig、あるいはGitの環境変数に依存する

なのでコミットログに記録されるアカウントを切り替えるなら

.gitconfigの場合

$ git config --global user.name "Mona Lisa"

$ git config --global user.email "email@example.com"

グローバルの.gitconfigにコミッター名とメアドを設定。

ローカル(リポジトリ単位のスコープ)で設定するなら

$ git config --local user.name "Mona Lisa"

$ git config --local user.email "email@example.com"

でOK。

環境変数で切り替えるなら

export GIT_COMMITTER_NAME="Mona Lisa"

export GIT_COMMITTER_EMAIL="email@example.com"
export GIT_AUTHOR_NAME="Mona Lisa"
export GIT_AUTHOR_EMAIL="email@example.com"

という具合にする。

環境変数を実際にリポジトリごとに切り替えたりする場合には、direnvを使うと自分は便利だと思っている。

direnvを使う方法はこちらのブログがすごくわかりやすい。


ようするにコミッターを切り替えるための情報を.gitconfigで管理したいなら、使いたいアカウントのnameとemailを.gitconfigに書けばOK。この場合globalとlocalの.gitconfigを巧みに使いわけることになる。

あるいはGit環境変数で管理したいなら、.envrcなりに環境変数をよしなに設定していく。

なおこれらコミッター名の切り替えに関しては以前書いたこの辺の話にも通ずる。

https://tech-1natsu.hatenablog.com/entry/2018/10/19/021855


認証まわりを使い分ける…プライベートリポジトリもcloneしたりpushしたい!

git addするときのコミッター情報を切り替えるのは上記の方法でOKだけど、git pushなりgit cloneするときの認証の場面では上記のコミッター情報の設定は関係がない。

関係ないとは言っても普通にパブリックリポジトリをCloneする場合は

$ git clone https://gitlab.com/1natsu172/example-public-repo.git

で問題なくクローンできる。

プライベートリポジトリでもCloneするなら

$ git clone https://gitlab.com/1natsu172/example-private-repo.git

Username for 'https://gitlab.com':
Password for 'https://gitlab.com':

という具合にリポジトリへのアクセス権を持ってるか聞かれるので正しいアカウント情報を打てばCloneできる。

毎回使いたいほうのアカウント名とパスワードを打てばアカウントを使い分けられますね。めでたしめでたし。

……めでたしなわけがない。毎回毎回パスワードを打つなんて人間のすることじゃない。


ユーザー名とパスワードをcredential helperに記憶してもらう

人間が毎回打つのは勘弁してほしい。なので記憶してもらうようにする。

MacOSの場合はGit自体に付属しているosxkeychain helperにお願いする。

$ git config --global credential.helper osxkeychain

これでglobalの.gitconfigosxkeychain helperを使うように書き込まれて、めでたく毎回パスワードを打たなくてよくなりました。


なおそもそもgit credential-osxkeychainが使えるかを確認したいなら、

$ git credential-osxkeychain

Usage: git credential-osxkeychain <get|store|erase>

こう返ってくればOKなよう。

上記のcredential helperことは実は全部Githubのヘルプに書かれている。


ところでこれでどうやって認証アカウントを切り替えるんですか?

『パスワード記憶してくれるようになったのはいいけど、どっちのアカウントで認証するかを指示してないじゃないか、プライベートリポジトリのアクセスはどうやって切り替えるんだ!』

わかります。

httpsではプライベートリポジトリのcloneをするときはこう。

ドメインの前に「ユーザー名@」をつける

https://<username>@<domain>/<repository-username>/<repository-name>.git

つまりgit cloneするときにこう

$ git clone https://hitonatsu@gitlab.com/1natsu172/example-private-repo.git


ユーザー名がhitonatsuのアカウントを使いたい場合の例


すると初回だけ

$ git clone https://hitonatsu@gitlab.com/1natsu172/example-private-repo.git

Password for 'https://hitonatsu@gitlab.com':

のようにパスワードを聞かれて、以降はcredential helperが憶えてくれる。


つまり初回のみでOK

リポジトリのhttps形式のURLをブラウザからゲットしようとすると


これはGitHubですが…


まあこういう感じ。

リポジトリを最初にcloneするときだけこれをコピーして

https://<username>@<domain>/~

形式に変えてcloneするだけでOK。以後は各アカウント毎にパスワードを憶えてくれる。

「ユーザー名@」をつけてcloneするとリポジトリのリモートURLはどうなるかというと

$ git remote -v

origin https://hitonatsu@gitlab.com/1natsu172/example-private-repo.git (fetch)
origin https://hitonatsu@gitlab.com/1natsu172/example-private-repo.git (push)

でちゃんと設定される。

既存のローカルリポジトリのリモートURLをこの形式に変えるなら普通にgit remote set-url origin {url}てな具合で普通にすればOKなはず。

credential helperhttps://<username>@<domain>ごとに記憶してURL判断してくれるっぽいので、これでうまくアカウントを切り替えられた。


ちなみにお察しの通りMacOSではキーチェーンアクセスに保存される。


GitHubじゃなくGitLabの例ですがちゃんとアカウント2件分保存されてますね



まとめ


  • コミッター情報



    • .gitconfigかGit環境変数で管理



  • 認証情報



    • credential helperを使ってアカウントパスワードを記憶

    • プライベートリポジトリをcloneするときはhttps://username@domain/~形式にする



だけ!

1回設定すればOK、プライベートリポジトリも「ユーザー名@」つけてcloneするだけで完全にラク。覚えやすい。



ハマり解決情報


GitHub Help 最強


  • ぶっちゃけGitのことでハマったらたいていGitHubのヘルプを見ればわかる


    • 検索しづらい見づらいですが…



  • Set up gitに沿って設定すればだいたいなんでもうまくいく




Q. リモートリポジトリとやりとりするときパスワード入れてもうまくいかない…

A.もしかして:2段階認証(2FA)

2段階認証(2FA)してるならcli上で聞かれるパスワード欄には生成したpersonal access tokenを入れる。


なにかまちがってることがありそうなので、もしありましたら編集リクエストお願いします :pray: