GitリポジトリのURL毎に自動でコミット時のGithubアカウントを切り替える

正確に書くと、originのドメイン毎にuser.emailuser.nameを切り替える、です。

僕の職場では、コードを社内に構築したGitHub Enterprise環境にpushしてて、こっちは社用のメールアドレスで登録しています。
一方で、個人的な開発をすることがある場合はGitHubを使うのですが、こっちは個人用のGmailアドレスです。

で、git configに個人用emailをグローバル設定してたりすると、うっかりGitHub Enterpriseのリポジトリにそっちでcommitしちゃったりしてしまうことがあるんですよね。
リポジトリ毎に git config --local user.email hoge@fuga.com とちゃんと設定すればいいんですが、大抵忘れてて後でrebase祭りになる……:innocent:

という具合でいろいろ面倒だったので、pre-commitで勝手に書き換えてくれるようにしてみました

こうなった

githubから適当にリポジトリをpullしてきてcommitする

$ git config --get user.email  # 元は会社アカウント(ここでの表示はダミーデータ)
ry023-yyyyyy@ry023-company.com
$ git config --get user.name
global_dummy

$ git commit --allow-empty -m dummy-commit # commitしようとするとrejectされ、設定が上書きされる
changed user.name to ry023
changed user.email to ry023-xxxxxxx@gmail.com
try again!

$ git config --get user.name # 設定が変わっていることを確認
ry023
$ git config --get user.email
ry023-xxxxxxx@gmail.com

$ git commit --allow-empty -m dummy-commit # もう一度やると、正しいアカウントでcommitされる
[master cd57d5b] dummy-commit
$ git show HEAD
commit cd57d5bd3bf8eb461d4532e9133a232a92aeab0b
Author: ry023 <ry023-xxxxxxx@gmail.com>
Date:   Sat Apr 14 16:29:35 2018 +0900

    dummy-commit

設定やら

gitのv2.9から、core.hooksPathというconfigからhookのpathを変更できるようになったらしいです。
以下のようにすると~/.git/hooksが全リポジトリの共通のhook置き場になります

$ mkdir -p ~/.git/hooks
$ git config --global core.hooksPath ~/.git/hooks/

~/.git/hooks/pre-commit というファイルを作って次のような感じのshell scriptを配置してやると終わりです!
頭の部分はよしなに変更してやってください
(実行権限が必要なので chwon +x ~/.git/hooks/pre-commitすることも忘れずに)

#!/bin/sh

#### アカウント設定。ここに書くか、bash_profileやらzsh_profileやらに書いておく ####
GITHUB_DOMAIN="github.com"
GITHUB_NAME="ry023"
GITHUB_EMAIL="ry023-xxxxxxx@gmail.com"

GHE_DOMAIN="your-company-github.com"
GHE_NAME="ry023"
GHE_EMAIL="ry023-yyyyyy@ry023-company.com"
###################################################################

raw_url="$(git remote get-url origin)"
if echo "$raw_url" | grep https; then
  # for https
  remote_domain=$(echo $raw_url | sed -e 's/https:\/\///' | awk -F'/' '{print $1}')
else
  # for ssh
  remote_domain=$(echo $raw_url | sed -e 's/^.*@\(.*\)/\1/' | awk -F'/' '{print $1}' | awk -F':' '{print $1}')
fi

case "$remote_domain" in
  "$GITHUB_DOMAIN" )
    NAME=$GITHUB_NAME
    EMAIL=$GITHUB_EMAIL
    ;;
  "$GHE_DOMAIN" )
    NAME=$GHE_NAME
    EMAIL=$GHE_EMAIL
    ;;
  * )
    echo "unknown remote domain $remote_domain"
    exit 0
    ;;
esac

FAIL=false

if [ "$(git config --local --get user.name)" != $NAME ]; then
  git config --local user.name $NAME
  echo "changed user.name to $NAME"
  FAIL=true
fi

if [ "$(git config --local --get user.email)" != $EMAIL ]; then
  git config --local user.email $EMAIL
  echo "changed user.email to $EMAIL"
  FAIL=true
fi

if $FAIL;then
  echo "try again!"
  exit 1
fi

余談: 本当はアカウントの変更からcommit完了までpre-commit内で一括してやりたかったのですが、どうやらpre-commitでアカウント変更してもそのコミット自体は前のアカウントのままになるようです。もっといいやり方あるのかな?

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.