読者の皆さまが普段使っているバージョン管理システムは何でしょうか?多くの会社さんと同様、KLabでは大多数のプロジェクトでGitを利用しています。
Gitでは全てのcommitについて名前とメールアドレスが記録されます。ところで、Git管理しているリポジトリ上で会社のメールアドレスと個人のメールアドレスが混ざることがありませんか?
KLab社内では大半のプロジェクトでGitHub Enterpriseを利用している一方、一部プロジェクトや公開用のリポジトリについてはgithub.comも併用しており、それぞれで登録メールアドレスが異なっていたりするため、間違いが起こりやすい状況になっています。
本稿では、そんなときでもリポジトリごとに適切なメールアドレスでcommitできるような~/.gitconfig
の書き方を紹介します。
今回紹介する手順は、リポジトリをgit clone
するタイミングでuser.name
およびuser.email
を自動的にgit config --local
で設定するようにした、というものです。また、その際の設定値をスクリプト側に書かず、~/.gitconfig
に書けるようにしました。
手順としては、まず~/.gitconfig
を次のように変更または追記します。
[init]
templatedir = ~/.git_templates/
[user]
name = Git Hanako
email = git@example.com
[user "ssh://git@ghe.example.jp/"]
email = hanako@ghe.example.jp
[user "https://ghe.example.jp/"]
email = hanako@ghe.example.jp
ただし、[user]
ブロックに書くメールアドレスはデフォルトのメールアドレス、[user <URL>]
ブロックに書くメールアドレスはリポジトリのURLに対応するメールアドレスです。
次に、この設定通りにGitのローカル設定を変更するためのフックスクリプトを設置します。次のように~/.git_templates/hooks/post-checkout
を作成します。
#!/bin/sh
PREVIOUS_HEAD=$1
NEW_HEAD=$2
BRANCH_SWITCH=$3
Z40="0000000000000000000000000000000000000000"
# Continue only when "git clone" has been executed.
if [ "$PREVIOUS_HEAD" != "$Z40" -o "$BRANCH_SWITCH" != "1" ]; then
exit
fi
origin_name="$(git remote | head -1)"
current_remote_url="$(git config --get --local remote.$origin_name.url)"
default_name="$(git config --get user.name)"
default_email="$(git config --get user.email)"
local_name="$(git config --local --get user.name)"
local_email="$(git config --local --get user.email)"
if [ "$current_remote_url" ]; then
case $current_remote_url in
*://*)
# Normalize URL: remove leading "git+"
# e.g. "git+ssh://user@host/path/" ==> "ssh://user@host/path/"
current_remote_url=$(echo $current_remote_url | sed 's/^git\+//')
;;
*:*)
# Convert scp-style URL to normal-form
# e.g. "user@host:path/" ==> "ssh://user@host/path/"
current_remote_url=$(echo $current_remote_url | sed 's/\(.*\):/ssh:\/\/\1\//')
;;
esac
if [ -z "$local_name" ]; then
name="$(git config --get-urlmatch user.name $current_remote_url)"
if [ "$name" != "$default_name" ]; then
git config --local user.name "$name"
fi
fi
if [ -z "$local_email" ]; then
email="$(git config --get-urlmatch user.email $current_remote_url)"
if [ "$email" != "$default_email" ]; then
git config --local user.email "$email"
fi
fi
else
echo "No remote URL"
fi
こうすることで、git clone
のタイミングでuser.name
とuser.email
が必要に応じて設定されるというわけです。
ただし、git init
してgit remote add
したような場合には対応できないので、注意が必要です。
~/.gitconfig
にはURLごとの設定が書けるスクリプトだけ紹介しても寂しいので、仕組みも紹介します。
Gitの設定は~/.gitconfig
に記述できますが、 Git 1.8.5からはリポジトリURLごとの設定が書けるようになりました。git-config
のman pageには次のような例が掲載されています。
; HTTP
[http]
sslVerify
[http "https://weak.example.com"]
sslVerify = false
cookieFile = /tmp/cookie.txt
これはリポジトリのホスト名によってhttp.sslVerify
を勝手に切り替えるような例です。設定値によっては、このように書くだけで勝手に設定を使い分けることができます。
一方で、user.email
などの設定はURLに紐付いているわけではないため、~/.gitconfig
を設定しただけでは反映されません。とはいえ、同じ枠組みを利用すればシンプルに設定が記述できますし、git config
の--get-urlmatch
オプションを使えば簡単に値が取り出せますから、今回はこれをgit clone
のフックスクリプトから利用したというわけです。
この仕組みを使えば、特定オーガナイゼーションのみ、もしくは特定リポジトリのみといった設定も可能ですので、他にも応用ができそうですよね。便利な使い方を思いついた方はぜひ教えてください!
@hnw
KLabのゲーム開発・運用で培われた技術や挑戦とそのノウハウを発信します。
合わせて読みたい
KLabのゲーム開発・運用で培われた技術や挑戦とそのノウハウを発信します。