🙆

dotfilesをGitHubで管理する

2024/02/04に公開

dotfiles(ホームディレクトリにある設定ファイル)をGitHubで管理する方法を紹介します。

GitHubで管理することのメリット

ざっとこんな感じでしょうか。

  • 複数のPC間で同一の設定を共有できる。
  • PC故障や誤削除などに備えたバックアップになる。
  • Gitで履歴管理するので簡単に戻すことができる。

手順

簡略化した説明になります。

  1. ローカルに管理用のディレクトリを作成し、GitHubにリモートリポジトリを作成します。

    リポジトリ名はdotfilesにするのが一般的なようです。

  2. 管理したいファイルをホームディレクトリからリポジトリがあるディレクトリにコピーします。ディレクトリの中にあるファイルはディレクトリごとコピーします。

  3. 次の章にあるインストール用スクリプトをinstallというファイル名でリポジトリがあるディレクトリにコピーし、実行権限を付与します。

    chmod u+x install
    
  4. インストール用のスクリプトを実行します。

    ./install
    

    どんなシンボリックリンクが作成されるかが表示されます。本当に作成してよいかの確認が表示されるので、問題なければ "y" を入力します。

    Dry run:
      mkdir -pv /Users/ikoba/.config
      mkdir -pv /Users/ikoba/.config/fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/config.fish /Users/ikoba/.config/fish/config.fish
      mkdir -pv /Users/ikoba/.config/fish/functions
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/open_finder.fish /Users/ikoba/.config/fish/functions/open_finder.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/start_walking.fish /Users/ikoba/.config/fish/functions/start_walking.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/git_update.fish /Users/ikoba/.config/fish/functions/git_update.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/select_ghq_repository.fish /Users/ikoba/.config/fish/functions/select_ghq_repository.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/use_java_version.fish /Users/ikoba/.config/fish/functions/use_java_version.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/select_docker_container.fish /Users/ikoba/.config/fish/functions/select_docker_container.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/select_docker_image.fish /Users/ikoba/.config/fish/functions/select_docker_image.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/open_vscode.fish /Users/ikoba/.config/fish/functions/open_vscode.fish
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/fish/functions/select_git_branch.fish /Users/ikoba/.config/fish/functions/select_git_branch.fish
      mkdir -pv /Users/ikoba/.config/peco
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/peco/config.json /Users/ikoba/.config/peco/config.json
      mkdir -pv /Users/ikoba/.config/karabiner
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.config/karabiner/karabiner.json /Users/ikoba/.config/karabiner/karabiner.json
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.ideavimrc /Users/ikoba/.ideavimrc
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.gitignore /Users/ikoba/.gitignore
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.rubocop.yml /Users/ikoba/.rubocop.yml
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.pryrc /Users/ikoba/.pryrc
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.gitconfig /Users/ikoba/.gitconfig
       ln -snfv /Users/ikoba/dev/src/github.com/ikoba/dotfiles/.pdbrc /Users/ikoba/.pdbrc
    
    ok? (y/N):
    
  5. インストール用スクリプトも含めてコミットし、リモートリポジトリにプッシュします。

以上で完了です。

インストール用スクリプト

macOS上で動作するスクリプトになります。

  • リポジトリにある設定ファイルのシンボリックリンクをホームディレクトリに作成します。
    → シンボリックリンクにすることでホームディレクトリにある設定ファイル、リポジトリにある設定ファイルのどちらを変更しても、もう一方にも反映されます。
  • 設定ファイルがディレクトリの中にある場合、ホームディレクトリにそのディレクトリが存在しない場合は作成します。mkdir -pで作成しているので中間ディレクトリも作成されます。
#!/bin/bash
#
# Install dotfiles
#
set -euo pipefail

cd "$(dirname "$0")"

REPO_DIR="$(pwd)"

function install_sub() {
  local execute=$1
  local path

  while IFS= read -rd '' path; do
    path="${path/.\//}"

    [[ "${path}" == "install" ]] && continue
    [[ "${path}" =~ ^\.git(\/.*)?$ ]] && continue
    [[ "${path}" =~ \.DS_Store$ ]] && continue
    # 他に除外したいファイルがあればここに追加します

    if [[ -d "${path}" ]]; then
      if [[ "${execute}" = 'true' ]]; then
        mkdir -pv "${HOME}/${path}"
      else
        echo "  mkdir -pv ${HOME}/${path}"
      fi
    elif [[ -f "${path}" ]]; then
      if [[ "${execute}" = 'true' ]]; then
        ln -snfv "${REPO_DIR}/${path}" "${HOME}/${path}"
      else
        echo "   ln -snfv ${REPO_DIR}/${path} ${HOME}/${path}"
      fi
    fi
  done < <(find . -mindepth 1 -print0)
}

echo "Dry run:"
install_sub 'false'
echo

read -rp "ok? (y/N): " yn
case "${yn}" in
  [yY]*)
    install_sub 'true'
    echo
    echo "finished"
    ;;
  *)
    echo "abort"
    ;;
esac

Discussion