Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
87
Help us understand the problem. What is going on with this article?
@KeyMama

複数のGitアカウントを手動切替不要で運用する

More than 1 year has passed since last update.

結論

  • git configのurlの設定を利用して、リポの中では自動的に目的のsshホストが使われるようにする。
  • git cloneが叩かれたことをtrap DEBUGで検知してコマンド実行前にフラグを立て、Githooksのpost-checkout内で、clone先ディレクトリの位置に応じて利用するgitアカウント情報をgitconfigに書き込む。

問題

一つのマシン上で複数のGithubアカウントを使い分けている人がどのくらいいるのかわかりませんが、私は仕事とプライベートのGithubアカウントを分けています。
案件によっては求めに応じてその会社用のアカウントを作ったりします。

ただ、複数持っていても運用がつらくなるのは避けたいです。

  • アカウントの切り替えやリポの設定を楽にしたい。全部自動にしたい。
  • SSHの設定を覚えてなくてもいいようにしたい。
  • 間違えて仕事のリポにプライベートのアカウントでコミットしてしたり、プライベートのリポに仕事のアカウントでコミットしたりするのを防ぎたい。(gitフックを使って職場のレポジトリに趣味のアカウントでcommitするのを防ぐという記事もあるんですが、コミットのときに実行されるのではなく、クローンのときに自動で設定したい)

ということで、

  1. 複数アカウントの設定のしかた
  2. 複数アカウントをどうやって楽に運用するか

を書きます。これによって、最初から最後まで(git clone前からpush後まで)アカウントの切り替えを手動でやる必要も、アカウントを意識する必要も無くなりました。ここまでやっている記事を見かけなかったので書いたのですが、密かにやっている人はたくさんいたり、Gitクライアントでこういうことができるものはあるかもしれない。

環境

macOS

sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.5
BuildVersion:   18F132

OpenSSH

ssh -V
OpenSSH_7.9p1, LibreSSL 2.7.3

Git

git --version
git version 2.23.0

仕事用のコードはworkディレクトリ配下、個人用のコードはprivateディレクトリ配下で管理しているとします。

設定のしかた

知っている方は飛ばしてください。

SSHキーを複数用意し、それぞれのGithubアカウントで公開鍵を設定

GithubではSSHキーを使い回せないのでアカウントの数分作ります。Githubじゃなくてもキーの使い回しは避けたほうがいいです。キーが流出しても被害が広がりにくいので。キーの作成方法がわからなければ、タイトルで煽ってるだけのお前らのSSH Keysの作り方は間違っている等を参考に。

~/.ssh/configの設定

Host github_p
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github_private
IdentitiesOnly yes
UseKeychain yes
AddKeysToAgent yes

Host github_w
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github_work
IdentitiesOnly yes
UseKeychain yes
AddKeysToAgent yes
  • Host 値が一意である必要があるので、それぞれ別の名前にします。
  • HostName, User ここはいつも通りgithub.comgitです。
  • IdentityFile 作成した秘密鍵のファイルパスです。適切に変更します。
  • IdentitiesOnly ssh-agentが複数のアイデンティティを保持しているときでも、ssh_configファイル内で明示的に設定されたアイデンティティのみを使用するかどうかを指定します。まさに今回のようなユースケースのためにある設定項目で、これを忘れると、github_pで接続したいのに、勝手に忖度してgithub_wで接続してしまう、みたいなことが起きます。
  • UseKeychain macOSのみ設定可能。パスワードやアカウント情報を管理するアプリであるKeychainにパスフレーズを保存するかどうか、そこから探すかどうかを指定します。macOSでない場合や、macOSでも古いバージョンのOpenSSHでは動かないらしいので、そんなオプションないって言われたらUseKeychainの行を消してください。
  • IgnoreUnknown ちなみに、そんなオプションないと言われるのを避けるためにこの設定の最初のほうに入れて、認識されないオプションを無視するという手もあるのですが、万が一、有効な設定なのにタイポしたために無視されるという危険もあるので、この設定は利用していません。
  • AddKeysToAgent キーとパスフレーズをssh-agentへ自動的に追加するかどうかを指定します。何度もssh-addするのは面倒くさいのでyesにします。この設定を使うのはやめようみたいな記事を見かけましたが、私はトラブったことはないです。その記事ではホントにこの設定が原因なのか検証されてなかったので、あまり気にしていません。

詳しくはman ssh_configを見てください。

どうやって運用するか

グローバルのユーザ情報を設定しない

git config --global --unset user.name
git config --global --unset user.email
~/.gitconfig
[user]
# nameが設定されていないことを確認
# emailが設定されていないことを確認
[url "github_p"]
# 件のSSHキーに関するURL短縮の設定がされていないことを確認
[url "github_w"]
# 件のSSHキーに関するURL短縮の設定がされていないことを確認

誤ったアカウントで操作したくないので、どのユーザ情報もデフォルトにはしないよう、globalにはユーザ情報は設定しません。git config --localのほうで適切に設定されない限り、git@github.comでアクセスできないようになります。安心。

ローカルで user.name, user.email, url..insteadOfの設定をする

cd 個人の/既存の/リポジトリの/パス
git config --local user.name "個人ユーザ名"
git config --local user.email "個人メールアドレス"
# url."ssh_configで設定したHostの値".insteadOf という形式にします
git config --local url."github_p".insteadOf "git@github.com"


cd 仕事の/既存の/リポジトリの/パス
git config --local user.name "仕事ユーザ名"
git config --local user.email "仕事メールアドレス"
# url."ssh_configで設定したHostの値".insteadOf という形式にします
git config --local url."github_w".insteadOf "git@github.com"
.git/config
[user]
  user = "個人ユーザ名"
  email = "個人メールアドレス"
[url "github_p"]
  insteadOf = "git@github.com"

すでにクローンされてローカルマシンにあるリポジトリについては、リポごとにユーザ情報を設定します。設定し直す必要があるリポジトリが多かったらスクリプト書いたほうがいいです。

ポイントはurlの設定です。

  • url.<base>.insteadOf gitコマンドを実行する際、insteadOfで指定した文字列で始まるURLについて、insteadOfで指定した文字列の部分が<base>で指定した文字列に書き換えられた状態で実行されます。 例えば、上記のgithub_pの設定をしてそのディレクトリ内でリモートとやり取りするgitコマンドを実行すると、 git@github.com:個人ユーザ/あるリポジトリ.git -> github_p:個人ユーザ/あるリポジトリ.git というふうに書き換えられて実行されます。git pushとか、明示的にURLを指定しないときもこの設定は有効なので便利です。git@github.com以外にも、任意の文字列を複数登録しておけます。
  • sshCommandという設定項目もあるのですが、SSHの設定は~/.sshにまとめたく、散り散りに管理したくないので使いません。

noreplyメールアドレスの利用(オプショナル)

ちなみに、これはオプショナルな設定ですが、色々な理由で個人のメールアドレスをさらしたくないケースがあると思います。その場合、登録したメールアドレスではなく、Githubから提供されるno-replyメールアドレスを利用することもできます。
Setting -> Emails -> Keep my email addresses privateをチェックするだけです。Primary email addressの説明のところにno-replyメールアドレスが表示されて、利用できるようになります。
参考: https://help.github.com/en/articles/setting-your-commit-email-address

git cloneのSSH設定を自動で切り替える

もうひと押し。
上記のリポごとの.git/configの設定は一度設定してしまえば良いのですが、最初のgit cloneのときにはそもそもローカルにリポがないので設定できません。毎回クローン後にいちいち設定するのも面倒ですし、間違いの元です。

方法1: 単純にgit cloneをラップするコマンドを作って、git colneを使わずにそれを使う

一番簡単な方法ですが、間違ってgit cloneを使ってしまうのが嫌ですし、仮に別のプラグインを入れてクローンしたりするとダメです。

方法2: cdとgitコマンドのラッパー関数を作ってエイリアスとして設定する

そこで以下のGistを作りました。Gist冒頭部のコメントの通りに設定して、rcファイル等に貼り付けてロードし直すと動きます。cdとgitコマンドをエイリアスで上書きしています。直接cdgitという名前で関数を定義しないのは、上書き前の挙動をさせたいときに\cd\gitだけでできるからです。
https://gist.github.com/KeyAmam/2cde31a9c2ca4b1af44251c3ac628dec

このGistが何をしてくれるかというと、
- git clone実行時のSSH設定の自動切り替え。workディレクトリ配下で実行した場合(直下ではなく、配下ならどこでもいい)はgithub_wprivateディレクトリ配下で実行した場合はgithub_p、それ以外のディレクトリでは切り替えなしでcloneするようになります。
- git clone後の、上記のuser.nameuser.emailurl.<base>.insteadOfの自動設定
- --force-urlオプションでgit clone時の自動切り替えOFF。
- GPGキーのキー生成とgitconfigへの自動設定(git clone実行前に、上記Gistの65行目をアンコメントし、別のGist https://gist.github.com/KeyAmam/74d4aefcd161410bf1487714b829a6ce~/.scripts/git-set-gpg-key.shに保存しておいた場合)

コードが散らばらないので良いのですが、こちらも別のプラグイン等を入れてcd以外でもディレクトリ移動したりすると具合が悪いので結局方法3にしました。

方法3: GitHooksでgit cloneのみをフックする

記事を書きました: GitHooksでgit cloneだけをフックする

GPGキーの設定(オプショナル)

これはオプショナルな設定ですが、自分のコミットであることの信頼性を高めるためにGPGキーを設定します。基本的に、リポごとではなく、アカウントごとに1つのGPGキーを設定してます。
git clone実行前に、上記Gistの65行目をアンコメントし、別のGist https://gist.github.com/KeyAmam/74d4aefcd161410bf1487714b829a6ce~/.scripts/git-set-gpg-key.shに保存しておくと、GPGキーの設定が走るようになります。
設定したいリポに行って、git-set-gpg-key.shを単体で実行することもできます。

GPGキー生成時に名前とメールアドレスを聞かれますが、Githubのアカウント名とメールアドレスを入れておきます。本名を聞かれますが本名である必要はありません。

ローカルの設定後、gpg --armor --export メールアドレスやGPGキーIDなどキーを特定できる文字列 | pbcopyでクリップボードにGPG公開鍵をコピーし、GithubのSettings -> SSH and GPG keys -> New GPG Keysで貼り付け保存で完了です。これでコミットするとGithub上でverifiedアイコンが表示されるのが確認できます。

まとめ

まとめると、以下2つの対策によって、複数のGithubアカウントを持っていても、ほとんどアカウントについて意識する必要がなくなりました。気にするのは、どのディレクトリの中でクローンするかだけです。

  • git configのurlの設定を利用して、リポの中では自動的に目的のsshホストが使われるようにする。
  • GitHooksでgit cloneのみをフックしてsshホストを自動的に書き込む。
87
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
KeyMama
塩漬けしていたサブアカウント。しがないWebアプリケーション開発者。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
87
Help us understand the problem. What is going on with this article?