hene

hene.dev

Dev Container 利用時は git/config の include / includeIf を避けた方が良い理由と対策

Dev Container 利用時は git/config の include / includeIf を避けた方が良い理由と対策

Dev Container 環境で git commit を行おうとした際、設定が反映されていないことに気づきました。

原因は、自分の dotfilesgit/config を管理する際に includeIfinclude を利用していたためでした。 Dev Container(VS Code) の仕様上、これらの設定方法とは相性が悪いため、その原因と回避策をまとめます。

なぜ include / includeIf を使わない方が良いのか

結論から言うと、Dev Container 起動時に include 先のファイルまでコピーされないからです。

VS CodeDev > Containers: Copy Git Config は、ローカルマシンの ~/.gitconfig(または ~/.config/git/config)をコンテナ内に自動的にコピーしてくれます。 しかし、これはそのファイル単体をコピーするだけであり、その中で path 指定している参照先のファイル(config_workconfig_private など)まではコピーしてくれません。

結果として、コンテナ内では参照先ファイルが見つからず、includeincludeIf の参照先ファイルの設定が読み込まれない状態になります。

Dev Container における gitconfig コピーの仕様

VS Code のデフォルト設定(dev.containers.copyGitConfig)が有効なので、Dev Container 起動時にローカルの Git 構成がコンテナへコピーされます。

dev.containers.copyGitConfig

これにより、通常はコンテナ内でもローカルと同じ Git のユーザー名やメールアドレスが使えるはずですが、includeincludeIf を使って設定している場合にのみ前述の問題が発生します。

解決策:ファイルを結合して単一の 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 つのファイルとなった configDev Container にコピーされるため、設定が正しく反映されるようになります。

所感と課題

この対応で基本的な設定は読み込まれるようになりましたが、Dev Container で自分が Git を使うにはまだやるべきことがありました。

例えば pre-commitgit-secrets などのツールは、設定ファイルがあってもツール自体がコンテナ内に存在しないため動きません。 これらを動かすには devcontainer.jsonfeatures などでインストールする必要があります。

しかし、git-secrets のような個人で設定していた内容を、チームで共有する Dev Container 設定に含めるべきかは悩みどころです。

Dev Container を活用しているひとが、個人の好みの設定(gitmoji など)と、チーム共通の設定をどのように共存させているのか気になりました・・・

少し調べてみると dotfilesDev Container に適用する方法があるようなので、今度試してみたいと思います。

関連記事