使用 dotfiles 和 stow 管理你的 dotfiles 使用 dotfiles 和 stow 管理你的 dotfiles
TLDR;
brew install stow
cd ~
git clone git@github.com:jcouyang/dotfiles.git
cd dotfiles
stow .
* 可能看标题你觉得我疯了,什么叫用 dotfiles 管理你的 dotfiles。
第一个单词 dotfiles 指将 HOME 目录下的 .XXX
(它们是真的字面意思dotfiles) 文件同步到 Github 上的方式。
通常情况下,我们在开发过程中装的大部分工具,都会在 HOME 目录下创建一个以 .
开头的文件或目录,放置配置或者状态。
因此我们希望的是用 github 版本管理这些 配置 ,而不是 状态 。
好吧,让我们来看看到底如何版本管理这些 “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_history
和
fish.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
- 先把 emacs 的 repo 加到我的 remote 里,给个名字 emacs
- 用 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 gnupg2
安装完之后需要生成一个 keypair
gpg --gen-key
输入名字,邮箱,密码之后,就 ok 了
然后呢,我并不希望手动的每次加密完再push 到我的私有 git 上(对,即使是私有 git,安全考虑我还是需要加密,绝对不能明文存储,就是这么任性)。
那么到底去哪弄一个私有 git 呢?如果没有,dropbox 就可以,然后现在的问题是如何在 push 的时候自动的 gpg 加密。
现在 git remote crypt 大法就该登场了,到这里 https://github.com/spwhitton/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::///Users/jcouyang/Dropbox/dotfiles-private.git
git push
你会被问到刚才创建 gpg keypair 时输入的密码,然后…
看,两坨 gpg 加密过的文件
LLAP 🖖