うんうん。わかるよ。
一生懸命書いた .zshrc や .vimrc をバックアップしたかったんだよね。
わかるよ。 全て受け止めてあげる。
Homeディレクトリをgitリポジトリにする
Homeディレクトリ(~)をGitで管理する場合、単純に git init ~ を実行してしまうと、.cache や大容量のバイナリ、SSH秘密鍵などの機密情報までトラッキング対象になり、非常に危険かつ扱いづらくなってしまいます。
そのため、実務でドットファイル(設定ファイル)群をGit管理する際は、全無視 .gitignore 方式を採用するのが一般的です。
gitignoreの例
*
!.gitignore
!.gitignore_global
!Readme.md
# 特殊ディレクトリ
!.config
# zsh関係
!.zshrc
# neovim関係
!.config/nvim
!.config/nvim/init.vim
!.config/nvim/init.lua
*で全てのディレクトリをignore対象にして、!Readme.mdなど必要なファイルを例外に入れていきます方式です。
実際のところ
1年近くそれで運用してたので反省がてら書きます。
良かったところ(メリット)
-
環境構築の爆速化
- 新しいPCや別環境への移行・展開がコマンド一発で完了する
-
設定のバックアップと履歴管理
- 過去の「動いていた状態」にいつでも安全に戻せる
つらかったところ(デメリット・課題)
-
直感的な重さ・レスポンス悪化
- Home直下がリポジトリ扱いになり、シェル表示や補完等のオーバーヘッドで動作が重く感じる
-
リポジトリ境界の曖昧さ
- サブディレクトリ作業時もHomeリポジトリの判定を拾ってしまい、コンテキストが混同する
-
手動コミットの煩わしさ
- 設定変更のたびに
add / commit / pushを挟むのが精神的ハードルになる
- 設定変更のたびに
-
環境差分の吸収・柔軟性の欠如
- OSやマシンごとの「ちょっとした設定の違い」を純粋なGitだけで分岐・管理するのが難しい
-
ゼロからの設定作成コスト
- 管理対象の選定や、最初の汎用的な設定ファイル作り自体に手間がかかる
Nix使えば解決するらしい?
ごめんなさい。乗り遅れました。 もう置いてかれました。
make使った管理方式(開発中)
makeを使って事前ビルド、 make installで適用する方式に変えてます。
事件(本題)
前述したように、makeを使う方式に切り替えてます。
ある程度いい感じになったので、homeに移してみようかなって思いました。
homeを空にする
-
git checkout --orphan clean
とりあえず、既存のzshrcをどかすためにorphanでクリーンなリポジトリを作りました。 -
git rm --cache -r *
ステージに元々あった.zshrcなどが残ってるのでgit rmで追跡から消します。 -
git clean -f *
追跡からも消したので、もう不要です。 これらをgit cleanで蹴散らしましょう。
> ls -la
total 0
drwxr-xr-x 2 nikki wheel 64 7月 26 18:35 .
drwxrwxrwt 72 root wheel 2304 7月 26 18:35 ..
!?
みたいなことになります。(実際には-rをつけてないので、ディレクトリは守られました)
git cleanは注意して扱おう
git push --forceも危険なんですが、 .envなど使ってる環境あれば、git cleanも注意して扱いましょう。 ファイル消すんで。
個人的に、git cleanは自主規制して、普通にrmで消すのが安全なんじゃないかなと思います。
Gemini的な視点でこの事故を分析すると:
git rm --cached について
git rm --cached を実行した瞬間、それまで追跡されていたファイルはGit視点で「ただの未追跡ファイル(untracked)」に変化します。
その状態で「未追跡ファイルを一括削除する git clean」を叩いたため、Gitが『ユーザーが消してほしい不要ファイル』だと正しく判断して忠実に実行してしまった……というのが今回のミスのからくりだと考えます。
誰もが一度は通る通過儀礼です
これはドットファイル直管理における「誰もが一度は通る通過儀礼」と言えます
git push --force の危険さは有名ですが、ローカルの未追跡ファイルを容赦なく消し去る git clean も同等に凶悪です。
特に git rm --cached との組み合わせは「一瞬で未追跡に化けた全ファイルを消し去るコンボ」として機能してしまうため、ドライラン(-n)なしでの実行は相当リスクが高い挙動だったと考えられます。
git clean を使うなら必ず事前に -n(ドライラン)を付けて消されるファイルを確認するか、大人しく手動で rm(または別ディレクトリへ待避)するようにしましょう
このアプローチ自体にリスクが孕んでます
「~(Homeディレクトリ)そのものをGitリポジトリにする」というアプローチ自体が、コマンド一発で全ファイルを巻き込むリスクを常に孕んでいることを象徴するエピソードだと考えます。
安全策をとるなら git clean に依存せず手動で移動・削除するか、そもそも ~ と Git リポジトリを切り離す管理ツール(chezmoi や Stow 等)へ移行するのが本質的な解決策になりそうです。
まとめ
私は、.zshrcをgit管理するのを悪い方式だとは思いません。
なので、これからも今回の反省を生かして、続けていきたいと考えています。
ただし、homeディレクトリをリポジトリにするのは流石にやめます。