git configのlocal・global・systemの違い|優先されるのはlocal

複数の端末でgitを使い始めたり、チーム開発に混ざったりすると、だいたい一度は設定が迷子になる。「user.nameってどこに書いたっけ」「このリポジトリだけコミットの名前が違う」みたいなやつ。MacとWindowsのように端末をまたいで開発していると、なおさら起きやすい。
原因はほぼ1つで、git configに「3つの階層」があることを知らないまま使っているからだと思う。逆に言うと、仕組みさえ分かれば設定の置き場所で迷うことはなくなる。
目次 / INDEX
git configは3層ある。狭い方が勝つ
結論から。git configには適用範囲の違う3つの層がある。
- system: そのPC全体。全ユーザ共通
- global: そのユーザ全体。自分のホームディレクトリ
- local: そのリポジトリだけ
そして優先順位は「local > global > system」。同じキーが複数の層に書いてあったら、範囲が狭い方が勝つ。globalに user.email = A、あるリポジトリのlocalに user.email = B と書いてあれば、そのリポジトリの中では B が有効になる。
コマンドのフラグもそのまま対応していて、--system / --global / --local で読み書きする層を指定する。
git config --global user.name "Your Name"
git config --local user.email "[email protected]"
ここでひとつ注意。リポジトリの中でフラグを省略して git config user.name "..." と書くと、既定はlocalに書かれる。
「globalを直したつもりがそのリポジトリだけ変わってた」はこの仕様が原因のはず。書き込むときはフラグを省略しない方が安全だと思う。
git config --global user.name を打ったことはあるけど意味は考えたことがない、という段階なら、git/GitHub入門の「最初の設定」を先に見ておいてほしい。この記事はその続きとして読める。
それぞれどのファイルに書かれるか
3層の実体はただのテキストファイルで、場所が違うだけ。対比するとこうなる。
| scope | 実体ファイル | 効く範囲 | よく置く設定 |
|---|---|---|---|
| local | リポジトリ内の .git/config | そのリポジトリだけ | user.emailの上書き、core.hooksPath |
| global | ホームの ~/.gitconfig | そのユーザの全リポジトリ | user.name / user.email、alias、core.editor |
| system | gitインストール先の設定ファイル | PCの全ユーザ | インストール時の既定値 |
.git/config はエディタで開けば普通に読める。git config --local --edit でも直接開ける。「設定がどこかに隠されている」わけじゃなくて、置き場所が3つあるだけ、と分かると一気に怖くなくなる。
systemは、gitをインストールしたときに入る全体設定で、普段自分で触ることはほぼない。だから学生の個人開発なら、意識するのはglobalとlocalの2つだけでいい。
どの設定をどの層に置くか
判断基準は「全リポジトリで同じでいいものはglobal、そのリポジトリ固有のものはlocal」。これだけ。具体的に振り分けるとこうなる。
user.nameとuser.emailは基本global。全リポジトリ共通の名乗りだから。
ただし、仕事用と個人用でメールアドレスを分けたいリポジトリがあるなら、そこだけlocalで上書きすればいい。優先順位でlocalが勝つので、globalの値はそのままで安全に切り替えられる。
aliasやcore.editorもglobal。alias.co = checkout みたいな短縮は全リポジトリで効いてほしいので、globalに置くと一度書くだけで済んで楽だ。
改行コードの扱いを決めるcore.autocrlfは、リポジトリよりも使っているOSの事情が出やすい設定なのでglobalに置くことが多い、くらいに覚えておけばいいと思う。aliasの具体的な選び方は git aliasのおすすめ設定 に分けて書いた。
逆にcore.hooksPathはlocalが妥当。フックの置き場所はリポジトリごとに違うからだ。gitフックの記事で「configはローカル設定だからcloneで配られない」と書いたのは、まさにこのlocal層の話だった。
出所を確かめる:—list —show-origin
設定が食い違ったとき、一番役に立つのがこれ。
git config --list --show-origin
有効な設定が1行ずつ、「どのファイル由来か」付きで全部出てくる。同じキーが複数行出てきたら、複数の層に重複して書かれているサインで、実際に効くのは一番下(優先順位で勝った方)になる。犯人探しはこのコマンドでほぼ終わる。
個別のキーだけ見たいときは git config user.email。これは優先順位で勝った「有効値」が返る。
層を指定して git config --global user.email とすれば、globalに書かれた値だけを確認できる。有効値と層の値を見比べると、どこで上書きされているかが分かる。
cloneしてもlocalは配られない
最後に落とし穴を1つ。localの実体である .git/config は、gitの管理外のファイルだ。つまりcloneしても相手には一切配られない。
だから、新しい端末でcloneした直後に「user.nameが空」「古いglobalの値のままコミットしてた」が起きる。リポジトリと一緒に設定も付いてくると思っていると、ここで裏切られる。localは「その場でもう一度設定するもの」と覚えておいた方がいい。
フックの置き場所の設定(core.hooksPath)がcloneで共有されないのも、まったく同じ理由だ。どちらもlocal層がgitの管理外だから起きる。
まとめ
指針は一言で足りる。「global = 名乗りと好み、local = そのリポジトリ固有」。これで置き場所に迷うことはほぼなくなるはずだ。
3層の優先順位や設定キーをもう少し体系立てて押さえたいなら、git/GitHub入門で基本コマンドと最初の設定を一周しておくと調べ直しが速い。
まずは自分の環境で一度これを叩いてみてほしい。
git config --list --show-origin
思ってなかった層から設定が来ていたら、それが今日の収穫だ!
よくある質問
git configのlocalとglobalの違いは?
globalはそのユーザの全リポジトリに効く設定で、実体はホームの ~/.gitconfig。localはそのリポジトリだけに効く設定で、実体はリポジトリ内の .git/config。同じキーが両方にあれば範囲の狭いlocalが勝つ。
user.nameやuser.emailはlocalとglobalのどちらに置く?
基本はglobal。全リポジトリ共通の名乗りだから。仕事用と個人用でメールアドレスを分けたいリポジトリだけ、localで上書きすれば安全に切り替えられる。
今の設定がどのファイルから来ているか調べるには?
git config --list --show-origin を打つと、有効な設定が1行ずつ由来のファイル付きで出る。同じキーが複数行出たら複数の層に重複して書かれているサインで、実際に効くのは一番下の行。