Dev Container 利用時は git/config の include / includeIf を避けた方が良い理由と対策
Dev Container 利用時は git/config の include / includeIf を避けた方が良い理由と対策
Dev Container 環境で git commit を行おうとした際、設定が反映されていないことに気づきました。
原因は、自分の dotfiles で git/config を管理する際に includeIf や include を利用していたためでした。
Dev Container(VS Code) の仕様上、これらの設定方法とは相性が悪いため、その原因と回避策をまとめます。
なぜ include / includeIf を使わない方が良いのか
結論から言うと、Dev Container 起動時に include 先のファイルまでコピーされないからです。
VS Code の Dev > Containers: Copy Git Config は、ローカルマシンの ~/.gitconfig(または ~/.config/git/config)をコンテナ内に自動的にコピーしてくれます。
しかし、これはそのファイル単体をコピーするだけであり、その中で path 指定している参照先のファイル(config_work や config_private など)まではコピーしてくれません。
結果として、コンテナ内では参照先ファイルが見つからず、include や includeIf の参照先ファイルの設定が読み込まれない状態になります。
Dev Container における gitconfig コピーの仕様
VS Code のデフォルト設定(dev.containers.copyGitConfig)が有効なので、Dev Container 起動時にローカルの Git 構成がコンテナへコピーされます。

これにより、通常はコンテナ内でもローカルと同じ Git のユーザー名やメールアドレスが使えるはずですが、include や includeIf を使って設定している場合にのみ前述の問題が発生します。
解決策:ファイルを結合して単一の config を生成する
git/config の設定を PC に合わせて切り替える - hene.dev の記事に記載したように、これまでは includeIf でファイルを分割していました。
今回は、Dev Container に対応させるため、セットアップ時にファイルを結合して、単一の git/config を生成する方式に変更しました。
1. dotfiles/git/config (変更前) の削除
以下のように path で別ファイルを読み込んでいましたが、これは削除します。
- [include]
- path = ~/dotfiles/git/config_common
- [includeIf "gitdir:/Users/work_pc_user_name/**"]
- path = ~/dotfiles/git/config_work
- [includeIf "gitdir:/Users/private_pc_user_name/**"]
- path = ~/dotfiles/git/config_private
2. 環境判定関数の用意(dotfiles/zsh/.my_functions/account_type.zshrc)
どの PC(環境)で動いているかを判定する関数を用意します。(以前から使用していたものを流用)
function account_type() {
ACCOUNT_TYPE=$1
if [[ -n "${ACCOUNT_TYPE}" ]]; then
echo "${ACCOUNT_TYPE}"
elif [[ $(whoami) == "<会社のユーザー名>" ]]; then
echo "company"
elif [[ $(whoami) == "<プライベートのユーザー名>" ]]; then
echo "private"
fi
}
3. 生成スクリプト (dotfiles/setup/copy_gitconfig.sh)
共通設定と環境固有の設定を cat で結合し、単一の git/config ファイルを生成します。
config_common: 共通設定config_$(account_type): PCごとの設定(config_company/config_private)
#!/bin/zsh
echo "Copy gitconfig"
# 共通設定と環境別設定を結合して出力
cat \
"$DOTFILES_PATH/config/git/config_common" \
"$DOTFILES_PATH/config/git/config_$(account_type)" > "$DOTFILES_PATH/config/git/config"
4. .gitignore の設定 (dotfiles/config/git/.gitignore)
生成される $DOTFILES_PATH/config/git/config は環境によって内容が変わるため、Git 管理から除外します。
config
5. シンボリックリンクの作成 (dotfiles/setup.sh)
生成されたファイルを ~/.config/git/config として読み込めるようにシンボリックリンクを貼ります。
# 略
## Git
mkdir -p $HOME/.config/git
# 生成された config ファイルへのシンボリックリンクを作成
ln -nfs "$DOTFILES_PATH/config/git/config" "$HOME/.config/git/config"
# 略
これで、物理的に 1 つのファイルとなった config が Dev Container にコピーされるため、設定が正しく反映されるようになります。
所感と課題
この対応で基本的な設定は読み込まれるようになりましたが、Dev Container で自分が Git を使うにはまだやるべきことがありました。
例えば pre-commit や git-secrets などのツールは、設定ファイルがあってもツール自体がコンテナ内に存在しないため動きません。
これらを動かすには devcontainer.json の features などでインストールする必要があります。
しかし、git-secrets のような個人で設定していた内容を、チームで共有する Dev Container 設定に含めるべきかは悩みどころです。
Dev Container を活用しているひとが、個人の好みの設定(gitmoji など)と、チーム共通の設定をどのように共存させているのか気になりました・・・
少し調べてみると dotfiles を Dev Container に適用する方法があるようなので、今度試してみたいと思います。
