dotfiles、1 回作って満足しちゃってませんか?変更をコミットし忘れてリモートとローカルの差分が増えて放置している...という人もいるかと思います(僕です)。この記事では dotfiles の更新忘れを防いで継続的に管理していく方法を紹介します。
目次
dotfiles とは?
dotfiles とはドット(.
)から始まる設定ファイル群、またはそれらを管理するリポジトリです。.zshrc
とか .vimrc
とかですね。必ずしもドット(.
)からファイル名が始まる必要はないと思います1。
dotfiles については検索すると色々出てきます。dotfiles 自体の詳細な説明は以下などを参照ください。
dotfiles リポジトリの更新を忘れないようにする
なぜ?
dotfiles リポジトリを作って、setup.sh
を書いて....と dotfiles をリポジトリで管理するのは多くの人が通ってきた道だと思います。
しかし dotfiles は作って終わりというものではありません。
ローカルの dotfiles が常に固定されるのは稀であり、内容は常に変化していくものだと思います。いつパソコンがおじゃんになってもいいように、リモートリポジトリは常に最新の内容にアップデートしておくべきです。
実際のところ、僕も 2 年くらい前から dotfiles リポジトリを始めましたが、さっぱり内容を更新していなかったためローカルにある dotfiles とはかけ離れた内容となってしまっていました。
どうやって?
dotfiles リポジトリを更新しない一番の理由は、リポジトリの存在を忘れてしまうことだと考えました。
各設定ファイルはシンボリックリンクとしてあるべき場所に紐づけられているので、dotfiles が入ったディレクトリの場所を考えなくても容易に編集できてしまいます。これは手軽に編集できるというメリットでもありますが、dotfiles リポジトリの存在を忘れてしまうというデメリットも孕んでいると考えます。
なので、強制的に dotfiles の存在を気づかせてもらえばいいのではないかと考えました。
というわけで作ったスクリプトが以下になります。
このスクリプトでは、「『ステージングしていない』ことと『リモートブランチとローカルブランチに差分がある』ことをチェックして、どちらかが条件を満たせば『変更をコミットしてプッシュするメッセージを表示する」ということを行います。
「ステージングしていない」ことの確認
5 行目の git -C "${dotfiles_home}" status --porcelain
では「ステージングしていない」ことを確認しています2。
--porcelain
はgit status
の結果をマシンリーダブルにするためのオプションです。変更がある場合はそれが標準出力されますが、変更が無い場合は何も出力されません。
変更がある場合
❯ git status --porcelain M zsh/.zshrc.check_update_dotfiles ❯
変更がない場合
❯ git status --porcelain ❯
このコマンドを test -n
の引数として渡すことで、変更があれば exitcode=0 (=true)
、変更がなければ exitcode=1 (=false)
とできます。
「リモートブランチとローカルブランチに差分がある」ことの確認
6 行目の git -C ${dotfiles_home} diff --exit-code --stat --cached origin/main
では「リモートブランチ(origin/main
)とローカルブランチに差分がある」ことを確認しています。
--exit-code
はgit diff
時に差分があると exit code=1 とするオプションです。--stat
はgit diff
の結果を簡略化するためのオプションであり、長々と diff の結果を表示させない、pager3を使わないように設定しています。--cached
はステージングされた変更、コミットを対象にするオプションです。これによって、push されているかどうかを判別できます。
このコマンドの結果を !
で反転することで、push されていなければ exitcode=0 (=true)
、push されていれば exitcode=1 (=false)
、とできます。
「変更をコミットしてプッシュするメッセージを表示する」
そして、「ステージングしていない」または「リモートブランチとローカルブランチに差分がある」のどちらかを満たしている場合に、7〜16 行目を使って「変更をコミットしてプッシュするメッセージを表示する」ことを行います。
結果
ローカルの dotfiles がリモートリポジトリと異なる状態で check_update_dotfiles.sh
を実行した結果が以下になります。
作ったスクリプトを ~/.zshrc
で呼び出すようにすることで、ターミナルを開くたびにローカルの dotfiles がリモートリポジトリと異なるかどうかを確認してくれます。
もし異なってた場合はターミナルを開くたびに以下のように「プッシュしろ!」と怒ってくれるわけですね。
これでコミット忘れが無くなってリモートの dotfiles を継続的に管理していけそうです💪 💪
おまけ:ぼくのかんがえたさいきょうの dotfiles
おまけです。僕の dotfiles を紹介します。
以下のリポジトリで管理しています。 github.com
特徴
- セットアップが簡単にできる
setup.sh
を叩くだけで必要なコマンドをインストールして dotfiles のシンボリックリンクを配置してくれる
- dotfiles を更新してもリポジトリが更新されていないと教えてくれる
- この記事の前半の内容
ディレクトリ構成
以下のような構成になっています。
それぞれの設定ファイルはルート直下に置くのではなく、コマンド名などでディレクトリを掘ってその中に配置しています。 初期設定に使うファイルはルート直下に配置しています。
セットアップ用ファイル
初期設定のためのファイル群です。
ファイル名 | 説明 |
---|---|
README.md | セットアップ方法が載ってる |
Brewfile | Homebrew でインストールしたライブラリが書かれている。brew bundle でインストールできる。(Brewfile で Homebrew のライブラリを管理しよう! - kakakakakku blog) |
setup.sh | 実行するだけで必要なライブラリのインストールと dotfiles のシンボリックリンクを配置してくれる |
setup.sh
setup.sh
を実行することで、Homebrew がインストールされているか確認、されていなければ Homebrew と Brewfile で指定されたライブラリをインストール、dotfiles のシンボリックリンクを配置を行なってくれます。新しい Mac を買ってもすぐに環境構築できますね。
各設定ファイル
各設定ファイルはそれぞれディレクトリに分かれています。
ディレクトリ名 | 入ってる設定ファイル | 説明 |
---|---|---|
git | .gitconfig , ignore 1 |
.gitconfig には delta の設定が入ってる |
vim | .vimrc |
あまりカスタマイズしてない |
zsh | .zshrc , .zshrc.* |
.zshrc.* は .zshrc から呼び出されるようになっている。 |
asdf | .tool_versions , .asdfrc |
asdf は様々なランタイムをバージョン管理するツール。anyenv をさらに広くした感じ。インターフェースが統一されているのが良い |
starship | starship.toml |
starship の設定ファイル。プロンプトに表示するパラメータをカスタマイズできる |
zsh関連
.zshrc
は適当に管理して内容が膨らみがちなのでこんな感じでファイルを分けて source
で呼び出すようにしています。この記事で説明した check_update_dotfiles.sh
もここで呼び出されています。(.zshrc.check_update_dotfiles
という名前ですが)
管理がしやすくなって良いですね。