ディレクトリごとに簡単にGitHubのアカウントを切り替える方法

はじめまして、Progateの村山です。 本記事はProgateAdventCalendarの15日目の記事です。

普段はSREチームでProgateの開発や運用を支える仕事をしており、Progateには今年の7月に入社しました。前職はElixirやk8sなどを使ったWebアプリケーションの開発や運用をしていました。

エンジニアであれば日常的に使うGitHubですが、仕事で個人用のアカウントを併用できない場合は仕事用のアカウントに切り替える必要があります。 本稿では作業ディレクトリ毎にGitHubのアカウントを切り替える方法を紹介します。

f:id:brian-pg8:20201214181521p:plain

GitとGitHubのアカウントについて

まずはじめにGitとGitHubは別物の概念で、GitHubはGitのリモートリポジトリをホスティングしているWebサービスです。GitはLinuxカーネルの開発者であるリーナスが開発した分散型バージョン管理システムでオープンソースソフトウェアです。GitHubはGitHub社が管理しているWebサービスです。GitHub以外のGitのリモートリポジトリのホスティングサービスとしてはBitBucketやGitLabが有名です。

リモートリポジトリとして利用する場合はGitのインストールの他に別途GitHubのアカウントを作る必要があります。また、リモートリポジトリへはSSH接続やHTTP(S)接続で通信を行うことができ、SSH接続が公開鍵を登録するだけなので一般的に多く使われています。一般公開されている認証が不要なリポジトリはHTTPで取得することも可能です。

余談ですが登録した公開鍵はHTTPリクエストで取得することが出来ます。

https://github.com/brian-pg8.keys

GitAuthorとGitCommiter

GitにはAuthorとCommiterという概念があります。Authorが設定されていないと git commit をすることが出来ません。また、GitHubで差分をマージするとCommiterとしてGitHubが指定されます。

[~/repo/]$ git show 4797c4a --format=full
commit 4797c4a9b225e6f1c664e82d4c0b99627f59be4e
Merge: 49127c4 21a9dc0
Author: "unsafe account" <b3BwYWkgaXMgZGVhZAo=@gmail.com>
Commit: GitHub <noreply@github.com>

    Merge pull request #XXX from Progate/super-repo
    

AuthorとCommiterの違いについてはSCMに以下のようにあります。

Git - コミット履歴の閲覧

authorとはその作業をもともと行った人、committerとはその作業を適用した人のことを指します。

作者と作業者という位置づけのようです。アカウントを変える場合はGitAuthorも変更する必要がありそうです。

GitHubのリポジトリへの認証

GitHub上にあるリポジトリをcloneまたはpushする時には様々な方法でアクセスすることが出来ますが、一般的にはSSH接続を使うことが多いように思います。

GitHubへのSSH接続はホストがgithub.com、ユーザがgit、IdentityFileはGitHubに登録してる鍵 で接続することが出来ます。接続方法を見るにGitHubはユーザの特定を秘密鍵の衝突により判定させています。つまり、複数の鍵をssh-agentに渡してしまうと、衝突させる順番によってアクセスしたときのユーザが異なってしまう問題が発生します。

また以下のコマンドでどのユーザでアクセスしているかを確認することが出来ます。

$ ssh -T git@github.com -i ~/.ssh/github_rsa
Hi "unsafe account"! You've successfully authenticated, but GitHub does not provide shell access.
$ ssh -T git@github.com -i ~/.ssh/pg8_rsa
Hi brian-pg8! You've successfully authenticated, but GitHub does not provide shell access.

git clonegit push するたびにSSHKeyを変更していてはものすごい手間になってしまいます。今回はこの手間を軽減する方法を紹介したいと思います。

全体構成

~/
├── .ssh/config ....(1)
├── .gitconfig ....(2)
├── account_A
│   ├── .gitconfig ....(3)
│   ├── repo1
│   └── repo2
└── account_B
    ├── .gitconfig ....(3)
    ├── repo3
    └── repo4

まず、アカウント別にディレクトリを分けます。それぞれの直下に .gitconfig を作成し、グローバルな .gitconfigincludeIf を使ってディレクトリ別に読み込む .gitconfig を振り分けます。最後に ssh config にホスト毎に読み込む鍵のペアを記載すると、git cloneする時にホストを切り替えることでアカウントを変更することが出来ます。

では具体的な設定を見ていきましょう。

(3) .gitconfigの設定

アカウント毎に必要なGit Authorの情報を設定します

[user]
  name = h.murayama
  email = h.murayama@prog-8.com

(2) .gitconfigの設定

グローバルな .gitconfigincludeif を使ってディレクトリごとに読み込む .gitconfig を指定します。

[includeIf "gitdir:~/account_A/"]
    path = ~/account_A/.gitconfig
[includeIf "gitdir:~/account_B/"]
    path = ~/account_B/.gitconfig

(1) ssh_configの設定

最後に ssh config にホストと鍵のペアを記録します。

Host github.com   # メインで使う場合
  HostName github.com                  
  User git                             
  IdentityFile ~/.ssh/github_rsa

Host progate.github.com  # アカウントを分けたいホスト
  HostName github.com                  
  User git                             
  IdentityFile ~/.ssh/pg8_rsa     

これによってホスト毎に利用する鍵が異なるので、ホストを変更することでアカウントを切り替える準備が整いました。

リポジトリ毎にアカウントを切り替える

git clone 時に指定するホスト名はssh_configで設定したホストをそのまま使うことが出来ます。 それにより以下のように利用する鍵を変更することが出来ます。

[~/ ]
 $ cd account_B/
[~/account_B]
 $ git clone git@progate.github.com:foo/bar

またこれらの設定はclone後も .git/config にremoteの設定が記録されるため一度設定しておけば、pullやpushの時にもホスト名を引き継ぐことが出来ます。

[remote "origin"]
        url = git@progate.github.com:foo/bar.git
        fetch = +refs/heads/*:refs/remotes/origin/*

注意点

既存のclone済みリポジトリは .git/config のホストを変更する必要があります。 私は以下のようなfindとsedで一気に変更しました。

$ find . -type f -name "config" | grep '.git' | xargs sed -i '' 's/github.com:[pP]rogate/progate.github.com:progate/g'

まとめ

リモートリポジトリのGitHubのアカウントをディレクトリごとに切り替える方法を紹介しました。 GitHubの様に毎日使うツールは常に使いやすくするのもエンジニアの仕事ですね!

次は16日目 kzk_maeda さんの記事です!お楽しみに!

[追記] GitHubアカウントの複数所持について

無料のGitHubアカウントは規約に対して非準拠となります。また有料のアカウントを複数所持することは認められているので、必要に応じて有料アカウントを作成する必要がありそうです。

GitHub Terms of Service - GitHub Docs

One person or legal entity may maintain no more than one free Account (if you choose to control a machine account as well, that's fine, but it can only be used for running a machine).