はじめまして、Progateの村山です。 本記事はProgateAdventCalendarの15日目の記事です。
普段はSREチームでProgateの開発や運用を支える仕事をしており、Progateには今年の7月に入社しました。前職はElixirやk8sなどを使ったWebアプリケーションの開発や運用をしていました。
エンジニアであれば日常的に使うGitHubですが、仕事で個人用のアカウントを併用できない場合は仕事用のアカウントに切り替える必要があります。 本稿では作業ディレクトリ毎にGitHubのアカウントを切り替える方法を紹介します。
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に以下のようにあります。
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 clone
や git push
するたびにSSHKeyを変更していてはものすごい手間になってしまいます。今回はこの手間を軽減する方法を紹介したいと思います。
全体構成
~/ ├── .ssh/config ....(1) ├── .gitconfig ....(2) ├── account_A │ ├── .gitconfig ....(3) │ ├── repo1 │ └── repo2 └── account_B ├── .gitconfig ....(3) ├── repo3 └── repo4
まず、アカウント別にディレクトリを分けます。それぞれの直下に .gitconfig
を作成し、グローバルな .gitconfig
に includeIf
を使ってディレクトリ別に読み込む .gitconfig
を振り分けます。最後に ssh config
にホスト毎に読み込む鍵のペアを記載すると、git clone
する時にホストを切り替えることでアカウントを変更することが出来ます。
では具体的な設定を見ていきましょう。
(3) .gitconfigの設定
アカウント毎に必要なGit Authorの情報を設定します
[user] name = h.murayama email = h.murayama@prog-8.com
(2) .gitconfigの設定
グローバルな .gitconfig
にincludeif
を使ってディレクトリごとに読み込む .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).