HOME | EDIT | RSS | ARCHIVE | INDEX | ABOUT

使用 dotfiles 和 stow 管理你的 dotfiles

可能看标题你觉得我疯了,什么叫用 dotfiles 管理你的 dotfiles。

第一个单词 dotfiles 指将 HOME 目录下的 .XXX (它们是真的字面意思dotfiles) 文件同步到 Github 上的方式。 通常情况下,我们在开发过程中装的大部分工具,都会在 HOME 目录下创建一个以 . 开头的文件或目录,放置配置或者状态。

因此我们希望的是用 github 版本管理这些 配置 ,而不是 状态

下面例子中的 dotfiles repo 在这里

好吧,让我们来看看到底如何版本管理这些 “dotfiles”。

使用 stow 管理 symlink

GNU stow 是管理符号链接(symlink)的一个小公举。只需要

brew install stow

或者如果你非 mac 机器,请访问官网看看如何安装

安装了 stow 之后,我们可以开始 symlink 一些 dotfiles 了。以 fish 和 omf 为例,它们本来的 HOME 目录下 的结构应该是这样的:

1: ⋊> ~/dotfiles on master ⨯ tree ~/.config                                             22:25:34
2: /Users/jcouyang/.config
3: ├── fish
4: │   ├── config.fish
5: │   ├── fish_history
6: │   └── fishd.a45e60d0d7e3
7: └── omf
8:     ├── bundle
9:     └── theme

stow 文件

注意看我们需要版本管理文件应该是 config.fish 和 omf 下的所有文件,于是,我将这些文件考到我新建 的 ~/dotfiles 目录下

mkdir ~/dotfiles/
cd ~/dotfiles
mkdir -p fish/.config/fish
mv ~/.config/fish/config.fish fish/.config/fish/
ls fish/.config/fish/

现在可以使用 stow 创建 symlink 了。

stow fish

瞅瞅 现在 ~/.config 变什么样了

⋊> ~/dotfiles on master ⨯ tree ~/.config                                             22:33:55
/Users/jcouyang/.config
├── fish
│   ├── config.fish -> ../../dotfiles/fish/.config/fish/config.fish
│   ├── fish_history
│   └── fishd.a45e60d0d7e3

config.fish 被链到了我创建的 dotfiles/fish 底下同样的目录中。 重要的是两个状态文件 fish_historyfish.blahblah 任然在 ~/.config/fish 下,我们并不想要他们到我们的 dotfiles 中来。

于是,这样其实每次修改 config.fish 都实际上是在修改 ~/dotfiles 下的 config.fish

stow 目录

另外我们在试试管理 omf(oh-my-fish),似乎 omf下面没有什么状态,bundle 和 theme 都是配置,所以 与其 symlink 文件,不如 symlink 整个 omf 目录。同样在 ~/dotfiles 目录下运行

mkdir -p ~/dotfiles/omf/.config
mv ~/.config/omf ~/dotfiles/omf/.config/omf
stow omf

这时候再看看 ~/.config

/Users/jcouyang/.config
├── fish
│   ├── config.fish -> ../../dotfiles/fish/.config/fish/config.fish
│   ├── fish_history
│   └── fishd.a45e60d0d7e3
└── omf -> ../dotfiles/omf/.config/omf

我们把整个 omf 目录都链到了 dotfile 目录下

push to github

下面看如何用 github 来管理这些 dotfiles

强烈推荐先安装 hub

brew install hub
hub create dotfiles
git add .
git commit -m "my awesome dotfiles"
git push origin master

就这么简单,你的配置文件就安全的放到了 github 上,并且以后每一次改动都再也不怕改挂了。

submodule vs subtree

但是我有些配置文件其实在另外一个 repo 上,这时候我怎么能跟这个 dotfiles repo 合到一起呢?

比如我的 emacs 配置文件,其实是单独管理在另一 repo 的。

这时候 git 为我们提供了两种方式来管理 submodule 和 subtree。 我用的是后一种,至于 submodule 为什么不适用,网上有大量文章解释,我就懒得翻译了。

⋊> ~/dotfiles on master ⨯ git subtree add --prefix emacs/.emacs.d git@github.com:jcouyang/.emacs.d.git master --squash

这行 subtree 命令把我的 emacs 配置从我的 repo 下下来作为 subtree,并 squash(合成一个) commits

这时我的 git树是这样的

\* commit b33c46bfebe4a28849aa967222555a4676fdb9f4 (HEAD -> master)
|\  Merge: 1b240f8 e6dacdc
| | Author: Jichao Ouyang <oyanglulu@gmail.com>
| | Date:   Thu Oct 29 21:33:06 2015 +0800
| |
| |     Merge commit 'e6dacdcd1f85cdcb3b5fa488edb7b8f31c297b3f' as 'emacs/.emacs.d'
| |
| * commit e6dacdcd1f85cdcb3b5fa488edb7b8f31c297b3f

可以看见把 我的 emacs repo merge 了进来,这样就跟在 dotfiles repo 的代码一样,该 commit 的 commit 该 push 的 push。

下面看如何 push 回我的 emacs repo。

比如我现在对 subtree emacs 做了改动并 commit 了。然后

git remote add emacs git@github.com:jcouyang/.emacs.d.git
git subtree push --prefix emacs/.emacs.d emacs master
  1. 先把 emacs 的 repo 加到我的 remote 里,给个名字 emacs
  2. 用 subtree push 直接 push 到 remote emacs,branch master

㊙ Sensitive dotfiles

有些 dotfiles 中可能涉及一些 token 或者密码,如果把他们 push 到 public 的 github 上, 有可能 肯定会对你个人或者公司造成巨大的损失(最近公司就开始扫描个人 github 账户了🙀 好紧张)。于是我们需要对这些敏感的 dotfiles 做加密。

比如 ~/.config/hub 里面,有我和公司的 github 的 token,我可不像这玩意被弄到 github 上。

目前最广泛使用的加密手段是 Gnupg,简称 gpg,一样使用 brew 装就好了

brew install gnupg

安装完之后需要生成一个 keypair

gpg --gen-key

输入名字,邮箱,密码之后,就 ok 了

然后呢,我并不希望手动的每次加密完再push 到我的私有 git 上(对,即使是私有 git,安全考虑我还是需要加密,绝对不能明文存储,就是这么任性)。

那么到底去哪弄一个私有 git 呢?如果没有,dropbox 就可以,然后现在的问题是如何在 push 的时候自动的 gpg 加密。

现在 git remote crypt 大法就该登场了,到这里 https://github.com/joeyh/git-remote-gcrypt 把 repo 下下来执行 ./install.sh, 之后就应该有 git-remote-gcrypt 这样一个命令,先别跑

关键在于见 remote 的时候。当我在 home 目录建了一个 dotfiles-private 的文件夹,stow 完各种敏感 dotfiles 之后

git init
git add .
git commit -m "some private dotfiles"
git remote add dropbox gcrypt::rsync:///Users/jcouyang/Dropbox/dotfiles-private.git
git push

你会被问到刚才创建 gpg keypair 时输入的密码,然后…

看,两坨 gpg 加密过的文件 image.png

LLAP 🖖