これは Atlassian が公開している Git チュートリアル記事 The best way to store your dotfiles: A bare Git repository を参考にして、筆者がドットファイルを Git で管理するまでに行った手順を解説した記事です。基となった Hacker New の投稿 は 2016 年ですが、このテクニックについて解説している日本語記事があまり見つからなかったため、書いてみました。
筆者が実際に公開しているリポジトリはこちらにあります
→ https://github.com/kosh04/dotfiles
用語のおさらい
-
ドットファイル: UNIX 系 OS における各種プログラムの設定ファイルのこと。
習慣としてファイル名がドット (".") で始まるものは「隠しファイル」とみなされ、通常の一覧表示では見えないようになっている。昔ながらのドットファイルは一般的なユーザが扱う必要のないファイルとしてホームディレクトリ直下に配置されることが多い。 -
dotfiles: それぞれの開発者が運用&公開しているドットファイルリポジトリの通称
→ 参考リンク:dotfiles.github.io - ベアリポジトリ: 作業ディレクトリ (worktree) を持たない、更新情報を格納しているディレクトリが剥き出し (bare) な状態のリポジトリ。
特徴
- ベアリポジトリ+ git コマンドラッパー
- ホームディレクトリ直下のドットファイルを管理できる (symlink 不要)
- 他ソフトのファイル管理に干渉しない/されない
この記事におけるテクニックの肝は以下のエイリアス定義にあります
alias dotfiles='git --git-dir=$HOME/.dotfiles.git --work-tree=$HOME'
軽く説明すると dotfiles
は Git リポジトリ (--git-dir=$HOME/.dotfiles.git
) と作業ディレクトリ (--work-tree=$HOME
) を明示して git コマンドを呼び出すだけの単純なラッパーコマンドです。元記事ではエイリアス config
や ~/.myconf
, ~/.cfg
などの名前を利用しているようです。
その辺はお好みでどうぞ。
個人的には「ドットファイルを管理するコマンド」ということで dotfiles
+ ~/.dotfiles.git
という名前で統一感を出すのがわかりやすいかなと思いました。
ドットファイルを共有するノウハウを書いた記事は他にも多々ありますが、このベアリポジトリを使ったテクニックでは、特徴その2が示すように 「ホームディレクトリのファイル構成」と「Git リポジトリのコンテンツ構成」が一対一にマッピングされる のが大きな特徴です。例えば ~/.config/git/config
は Git リポジトリ内でもそのまま .config/git/config
を指します。そのため dotfiles のセットアップ作業でよく見かける「シンボリックリンクを貼る工程」が不要となります。シンプルさはとても大事。
やろうと思えばホームディレクトリを直接 git の管理配下にする運用も可能です(実際そういった解説記事もあります)。一見シンプルそうですが、その場合ソースコード管理に対応したエディタや Git クライアントなどのソフトウェアでは ~/.git
ディレクトリが影響を及ぼす可能性があります。
その点 dotfiles
コマンドは他ソフトのファイル管理に干渉することなく閉じた環境でのリポジトリ操作を提供します。コマンド自体は単なる git のラッパーなので、セットアップ例を見れば分かるように git とほとんど同じ感覚で利用できるのもポイントです。
もちろん欠点もあります。
Github Desktop をはじめとする 各種 Git クライアントは素の状態ではベアリポジトリに対するソースコード管理に対応していません(要出典; 筆者が無知なだけの可能性もあります)。
必然的にリポジトリ操作の殆どを CUI で行うことが前提となるため、普段からターミナル作業に慣れている人向けのテクニックといえるでしょう。
セットアップ
ようやく本題。
まずはホームディレクトリ以下に空のベアリポジトリを立ち上げます。
あらかじめ github などで新規の空リポジトリを作成しておいて、それをベアリポジトリとしてクローンすると、リモートリポジトリの設定が省けて少しだけ簡単になります。
ちなみにベアリポジトリのディレクトリ名は末尾に .git
を付与するのが慣例らしいです。参考リンク: Pro Git ja
$ git init --bare ~/.dotfiles.git
あるいは
$ git clone --bare <repository_url> ~/.dotfiles.git
次にリポジトリ操作用コマンド dotfiles
の定義といくつかの設定を行います。
キー status.showUntrackedFiles
にはステータス表示時に未追跡のファイル一覧を隠す
フラグを設定します。これは git status --untracked-files=no
と同じ効果が得られます。
$ alias dotfiles='git --git-dir=$HOME/.dotfiles.git --work-tree=$HOME'
$ alias dotfiles >> ~/.bashrc
$ dotfiles config status.showuntrackedfiles no
実際のコンテンツをリポジトリから $HOME
にチェックアウトします(別マシンにてリポジトリの作成とプッシュが済んでいる場合)
$ dotfiles checkout
この時チェックアウトによって元から存在するファイルが上書きされる可能性がある場合は、問題のあるファイル一覧を出力してエラー終了するかもしれません。
error: The following untracked working tree files would be overwritten by checkout:
.bashrc
.config/git/config
Please move or remove them before you can switch branches.
Aborting
その場合はそれらのファイルを退避させた後、改めてチェックアウトします。以下のコマンド例ではバックアップ用のディレクトリを掘って、アーカイブ作成コマンド (tar
) を利用したファイルのバックアップを行っています。
$ mkdir -p ${BACKUP_DIR=~/.dotfiles.bak}
$ dotfiles checkout 2>&1 |\
grep $'^\t' |\
cut -c 2- |\
tar cf - -T - |\
tar xvf - -C "${BACKUP_DIR}"
$ dotfiles checkout --force
これでセットアップは完了しました。あとは dotfiles
コマンドを利用してドットファイルのバージョン管理を行うだけです。ファイルの更新が済んだら適当なリモートリポジトリ宛にプッシュします。
$ dotfiles status
$ dotfiles add .vimrc
$ dotfiles commit -m "Add vimrc"
$ dotfiles add .bashrc
$ dotfiles commit -m "Add bashrc"
$ dotfiles remote add origin <repository_url> (新規に git init でリポジトリを作成した場合のみ)
$ dotfiles push origin master
Git クライアントを利用したい
Git クライアントは便利ですが、先述したとおりベアリポジトリをそのまま扱うことはできません。
これには制限付きですが解決策があります。 dotfiles
コマンド経由で外部コマンドを呼び出すことで、肝である Git リポジトリとワークツリーの情報を引き継がせた状態でプログラムを起動させることができます。内部的には環境変数 GIT_DIR
, GIT_WORK_TREE
が子プロセスに継承されるようです。
例えば Tig (ターミナルで動作する Git クライアント) を起動するエイリアスを定義すると次のように実行できます。
$ dotfiles config alias.tig '!tig'
$ dotfiles tig status
とはいえ、その他の Git クライアントでも期待通りに動作するかは保証できません :p