direnvと環境変数を使ってGitのユーザ名、メールアドレス、SSH KEYをリポジトリ毎に切り替える

2021-08-05Bash,Git,Github

はじめに

Github を使って複数のプロジェクトを兼任していると、Git の複数アカウントを切り替えて使う必要がある場合があります。

僕は諸事情により Github アカウントを仕事用 x2、個人用 x1 を所有しています。

よく知られている方法としては、
以下のように git config --local コマンドで切り替えるやり方があります。

$ git config --local user.name "アカウント"
$ git config --local user.email "メールアドレス"
$ git config --local core.sshCommand="ssh -i ~/.ssh/ANOTHER_ID_RSA"

こういったマルチアカウント利用ケースにて、 環境変数を使って Git の ユーザ名(username)e-mail(email)SSH KEY の切り替え作業を効率化するための方法について紹介します。

検証環境

$ uname -moi
x86_64 MacBookPro16,1 Darwin

$ bash -version | head -n 1
GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin20.3.0)

$ git --version
git version 2.32.0

前提条件(必要なツール)

今回は direnv というツールを利用することを前提としています。

direnv については、過去のエントリでも紹介しているのでぜひご参考ください。

Git の挙動は「環境変数」を使って変更できる

Git の設定といえば git config コマンドを使ったり ~/.gitconfig ファイルを編集したりといった方法がよく利用されます。

上記以外にも、シェルの 環境変数 を使って動作を変更することができます。

今回利用する環境変数は以下の 3 つになります。

  • GIT_AUTHOR_EMAIL
  • GIT_AUTHOR_NAME
  • GIT_SSH_COMMAND

それでは早速、direnv と 上記の環境変数を使った設定の自動切り替えのやり方について見ていきましょう。

~/gitconfig から設定を読み込む (デフォルトの挙動)

git commit を何度か実行し、コミット時の usernameemail がどのように変わっていくかをお見せしたいと思います。

まずは適当な作業ディレクトリを作成した後、Git のローカルリポジトリを作成します。

# 適用な作業ディレクトリを作成
$ mkdir -p /private/tmp/work/

# Gitのローカルリポジトリを作成
$ git init
Initialized empty Git repository in /private/tmp/work/.git/

ここからファイルを追加し、コミットしてみます。

まずは 1 つめのファイルを追加します。

# 空のファイルを作成
$ touch 1.txt

# ファイルを追加
$ git add 1.txt

# コミット
$ git commit -m "first commit."
[main (root-commit) 5ffe0d7] first commit.
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 1.txt

正常にコミットされました。
ログを確認すると、 username = genzouwemail = genzouw@gmail.com となっていることがわかります。
この設定は僕の ~/.gitconfig ファイルに設定されている内容であり、デフォルトの挙動となります。

$ git log
commit 5ffe0d71e21a80161387c8beb8c23ad30f21cd9a (HEAD -> main)
Author: genzouw <genzouw@gmail.com>

    first commit.

環境変数から設定を読み込む

今度は git commit 実行前に GIT_AUTHOR_NAMEGIT_AUTHOR_EMAIL の 2 つの環境変数を設定してみます。

それぞれ genzouw2genzouw2@gmail.com という値を設定しています。

$ export GIT_AUTHOR_NAME=genzouw2

$ export GIT_AUTHOR_EMAIL=genzouw2@gmail.com

2 つめのファイルを追加し、コミットしてみます。

# 空のファイルを作成
$ touch 2.txt

# ファイルを追加
$ git add 2.txt

# コミット
$ git commit -m "second commit."
[main 9e196fc] second commit.
Author: genzouw2 <genzouw2@gmail.com>
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 2.txt

コミット時のメッセージからもすでにわかりますが、
ログを確認すると、 username = genzouw2email = genzouw2@gmail.com となっていることがわかります。
~/.gitconfig ファイルに設定されている内容を利用せず、先程設定した環境変数が利用されていることがわかります。

$ git log
commit 9e196fc761489dae0b355cb1b877b14980dea3ec (HEAD -> main)
Author: genzouw2 <genzouw2@gmail.com>

    second commit.

commit 5ffe0d71e21a80161387c8beb8c23ad30f21cd9a
Author: genzouw <genzouw@gmail.com>

    first commit.

ローカルリポジトリのディレクトリに移動したときに自動的に環境変数が適用されるようにする

毎回 GIT_AUTHOR_NAMEGIT_AUTHOR_EMAIL の 2 つの環境変数を設定したり、解除したりは面倒です。

そこで direnv を利用します。

direnv がインストールされていると、
.envrc というファイルが置かれているディレクトリ配下(サブディレクトリでも OK)に cd で移動したタイミングで .envrc に書かれている環境変数が自動的に適用されます。
逆にこのディレクトリ配下から抜け出すと環境変数が unset されます。

再び、2 つの環境変数 GIT_AUTHOR_NAMEGIT_AUTHOR_EMAIL に新しい値を設定した後、コミットしてみたいと思います。
ただし、環境変数は .envrc ファイルに記述することにします。

また、値はそれぞれ genzouw3genzouw3@gmail.com とします。

# .envrcファイルを作成
$ cat <<'EOF' > .envrc
export GIT_AUTHOR_NAME=genzouw3
export GIT_AUTHOR_EMAIL=genzouw3@gmail.com
EOF

direnv: error /private/tmp/work/.envrc is blocked. Run `direnv allow` to approve its content

# direnvに .envrc の環境変数の読み込みを許可する(セキュリティ上必要な操作)
$ direnv allow
direnv: loading /private/tmp/work/.envrc
direnv: export ~GIT_AUTHOR_EMAIL ~GIT_AUTHOR_NAME

3 つめのファイルを追加し、コミットしてみます。

$ touch 3.txt

$ git add 3.txt

$ git commit -m "third commit."
[main 74a3bc5] third commit.
Author: genzouw3 <genzouw3@gmail.com>
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 3.txt

ログを確認します。
コミットした際のユーザ名、メールアドレス は想定した値になっています。

$ git log
commit 74a3bc550ee6bed63499ff10a2e6e069bbc7d2d0 (HEAD -> main)
Author: genzouw3 <genzouw3@gmail.com>

    third commit.

commit 9e196fc761489dae0b355cb1b877b14980dea3ec
Author: genzouw2 <genzouw2@gmail.com>

    second commit.

commit 5ffe0d71e21a80161387c8beb8c23ad30f21cd9a
Author: genzouw <genzouw@gmail.com>

    first commit.

.envrc ファイルを無視リストに追加しておく

git statusgit diff 実行時に毎回 .envrc ファイルがステージング前のファイルとして検出されると煩わしいです。

そこで、 .envrc ファイルを Git のグローバル無視リストとして設定しましょう。

$ echo .envrc >> ~/.config/git/ignore

git push 時に利用する SSH KEY も切り替える

git commit までは自動的に切り替える仕組みができました。

最後に git push 実行時に利用する SSH KEY も自動的に切り替わるようにしましょう。

GIT_SSH_COMMAND 環境変数を指定すると、git push を実行したときに内部で使われる ssh コマンドにオプションを指定することができます。

以下のように ssh コマンドに -i オプションを付与し利用したい秘密鍵を指定します。

$ cat <<'EOF' >> .envrc
export GIT_SSH_COMMAND="ssh -i ~/.ssh/genzouw3.rsa"
EOF

$ cat .envrc
export GIT_AUTHOR_NAME=genzouw3
export GIT_AUTHOR_EMAIL=genzouw3@gmail.com
export GIT_SSH_COMMAND="ssh -i ~/.ssh/genzouw3.rsa"

この状態で git push すると、 普段利用されている ~/.ssh/id_rsa~/.ssh/config の設定に優先して環境変数に指定した鍵が利用されます。

ひとこと

git push したときに利用するSSH KEYをなんとかしたい場合に便利です。

2021-08-05Bash,Git,Github